mirror of
https://github.com/torvalds/linux.git
synced 2024-12-30 23:02:08 +00:00
nfsd: Ensure knfsd shuts down when the "nfsd" pseudofs is unmounted
In order to ensure that knfsd threads don't linger once the nfsd pseudofs is unmounted (e.g. when the container is killed) we let nfsd_umount() shut down those threads and wait for them to exit. This also should ensure that we don't need to do a kernel mount of the pseudofs, since the thread lifetime is now limited by the lifetime of the filesystem. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
f988a7b71d
commit
c6c7f2a84d
@ -51,9 +51,6 @@ struct nfsd_net {
|
||||
bool grace_ended;
|
||||
time64_t boot_time;
|
||||
|
||||
/* internal mount of the "nfsd" pseudofilesystem: */
|
||||
struct vfsmount *nfsd_mnt;
|
||||
|
||||
struct dentry *nfsd_client_dir;
|
||||
|
||||
/*
|
||||
@ -130,6 +127,9 @@ struct nfsd_net {
|
||||
wait_queue_head_t ntf_wq;
|
||||
atomic_t ntf_refcnt;
|
||||
|
||||
/* Allow umount to wait for nfsd state cleanup */
|
||||
struct completion nfsd_shutdown_complete;
|
||||
|
||||
/*
|
||||
* clientid and stateid data for construction of net unique COPY
|
||||
* stateids.
|
||||
|
@ -7326,14 +7326,9 @@ nfs4_state_start_net(struct net *net)
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
int ret;
|
||||
|
||||
ret = get_nfsdfs(net);
|
||||
ret = nfs4_state_create_net(net);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = nfs4_state_create_net(net);
|
||||
if (ret) {
|
||||
mntput(nn->nfsd_mnt);
|
||||
return ret;
|
||||
}
|
||||
locks_start_grace(net, &nn->nfsd4_manager);
|
||||
nfsd4_client_tracking_init(net);
|
||||
if (nn->track_reclaim_completes && nn->reclaim_str_hashtbl_size == 0)
|
||||
@ -7403,7 +7398,6 @@ nfs4_state_shutdown_net(struct net *net)
|
||||
|
||||
nfsd4_client_tracking_exit(net);
|
||||
nfs4_state_destroy_net(net);
|
||||
mntput(nn->nfsd_mnt);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1416,6 +1416,8 @@ static void nfsd_umount(struct super_block *sb)
|
||||
{
|
||||
struct net *net = sb->s_fs_info;
|
||||
|
||||
nfsd_shutdown_threads(net);
|
||||
|
||||
kill_litter_super(sb);
|
||||
put_net(net);
|
||||
}
|
||||
@ -1428,18 +1430,6 @@ static struct file_system_type nfsd_fs_type = {
|
||||
};
|
||||
MODULE_ALIAS_FS("nfsd");
|
||||
|
||||
int get_nfsdfs(struct net *net)
|
||||
{
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
struct vfsmount *mnt;
|
||||
|
||||
mnt = vfs_kern_mount(&nfsd_fs_type, SB_KERNMOUNT, "nfsd", NULL);
|
||||
if (IS_ERR(mnt))
|
||||
return PTR_ERR(mnt);
|
||||
nn->nfsd_mnt = mnt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int create_proc_exports_entry(void)
|
||||
{
|
||||
|
@ -93,13 +93,12 @@ int nfsd_get_nrthreads(int n, int *, struct net *);
|
||||
int nfsd_set_nrthreads(int n, int *, struct net *);
|
||||
int nfsd_pool_stats_open(struct inode *, struct file *);
|
||||
int nfsd_pool_stats_release(struct inode *, struct file *);
|
||||
void nfsd_shutdown_threads(struct net *net);
|
||||
|
||||
void nfsd_destroy(struct net *net);
|
||||
|
||||
bool i_am_nfsd(void);
|
||||
|
||||
int get_nfsdfs(struct net *);
|
||||
|
||||
struct nfsdfs_client {
|
||||
struct kref cl_ref;
|
||||
void (*cl_release)(struct kref *kref);
|
||||
|
@ -596,6 +596,37 @@ static const struct svc_serv_ops nfsd_thread_sv_ops = {
|
||||
.svo_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static void nfsd_complete_shutdown(struct net *net)
|
||||
{
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
|
||||
WARN_ON(!mutex_is_locked(&nfsd_mutex));
|
||||
|
||||
nn->nfsd_serv = NULL;
|
||||
complete(&nn->nfsd_shutdown_complete);
|
||||
}
|
||||
|
||||
void nfsd_shutdown_threads(struct net *net)
|
||||
{
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
struct svc_serv *serv;
|
||||
|
||||
mutex_lock(&nfsd_mutex);
|
||||
serv = nn->nfsd_serv;
|
||||
if (serv == NULL) {
|
||||
mutex_unlock(&nfsd_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
svc_get(serv);
|
||||
/* Kill outstanding nfsd threads */
|
||||
serv->sv_ops->svo_setup(serv, NULL, 0);
|
||||
nfsd_destroy(net);
|
||||
mutex_unlock(&nfsd_mutex);
|
||||
/* Wait for shutdown of nfsd_serv to complete */
|
||||
wait_for_completion(&nn->nfsd_shutdown_complete);
|
||||
}
|
||||
|
||||
bool i_am_nfsd(void)
|
||||
{
|
||||
return kthread_func(current) == nfsd;
|
||||
@ -618,11 +649,13 @@ int nfsd_create_serv(struct net *net)
|
||||
&nfsd_thread_sv_ops);
|
||||
if (nn->nfsd_serv == NULL)
|
||||
return -ENOMEM;
|
||||
init_completion(&nn->nfsd_shutdown_complete);
|
||||
|
||||
nn->nfsd_serv->sv_maxconn = nn->max_connections;
|
||||
error = svc_bind(nn->nfsd_serv, net);
|
||||
if (error < 0) {
|
||||
svc_destroy(nn->nfsd_serv);
|
||||
nfsd_complete_shutdown(net);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -671,7 +704,7 @@ void nfsd_destroy(struct net *net)
|
||||
svc_shutdown_net(nn->nfsd_serv, net);
|
||||
svc_destroy(nn->nfsd_serv);
|
||||
if (destroy)
|
||||
nn->nfsd_serv = NULL;
|
||||
nfsd_complete_shutdown(net);
|
||||
}
|
||||
|
||||
int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
|
||||
|
Loading…
Reference in New Issue
Block a user