Skip to content

Commit 681370f

Browse files
author
J. Bruce Fields
committed
nfsd4: fix nfsdfs reference count loop
We don't drop the reference on the nfsdfs filesystem with mntput(nn->nfsd_mnt) until nfsd_exit_net(), but that won't be called until the nfsd module's unloaded, and we can't unload the module as long as there's a reference on nfsdfs. So this prevents module unloading. Fixes: 2c830dd ("nfsd: persist nfsd filesystem across mounts") Reported-and-Tested-by: Luo Xiaogang <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]>
1 parent 22cf841 commit 681370f

File tree

3 files changed

+22
-11
lines changed

3 files changed

+22
-11
lines changed

fs/nfsd/nfs4state.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7912,9 +7912,14 @@ nfs4_state_start_net(struct net *net)
79127912
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
79137913
int ret;
79147914

7915-
ret = nfs4_state_create_net(net);
7915+
ret = get_nfsdfs(net);
79167916
if (ret)
79177917
return ret;
7918+
ret = nfs4_state_create_net(net);
7919+
if (ret) {
7920+
mntput(nn->nfsd_mnt);
7921+
return ret;
7922+
}
79187923
locks_start_grace(net, &nn->nfsd4_manager);
79197924
nfsd4_client_tracking_init(net);
79207925
if (nn->track_reclaim_completes && nn->reclaim_str_hashtbl_size == 0)
@@ -7984,6 +7989,7 @@ nfs4_state_shutdown_net(struct net *net)
79847989

79857990
nfsd4_client_tracking_exit(net);
79867991
nfs4_state_destroy_net(net);
7992+
mntput(nn->nfsd_mnt);
79877993
}
79887994

79897995
void

fs/nfsd/nfsctl.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,18 @@ static struct file_system_type nfsd_fs_type = {
14241424
};
14251425
MODULE_ALIAS_FS("nfsd");
14261426

1427+
int get_nfsdfs(struct net *net)
1428+
{
1429+
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1430+
struct vfsmount *mnt;
1431+
1432+
mnt = vfs_kern_mount(&nfsd_fs_type, SB_KERNMOUNT, "nfsd", NULL);
1433+
if (IS_ERR(mnt))
1434+
return PTR_ERR(mnt);
1435+
nn->nfsd_mnt = mnt;
1436+
return 0;
1437+
}
1438+
14271439
#ifdef CONFIG_PROC_FS
14281440
static int create_proc_exports_entry(void)
14291441
{
@@ -1451,7 +1463,6 @@ unsigned int nfsd_net_id;
14511463
static __net_init int nfsd_init_net(struct net *net)
14521464
{
14531465
int retval;
1454-
struct vfsmount *mnt;
14551466
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
14561467

14571468
retval = nfsd_export_init(net);
@@ -1478,16 +1489,8 @@ static __net_init int nfsd_init_net(struct net *net)
14781489
init_waitqueue_head(&nn->ntf_wq);
14791490
seqlock_init(&nn->boot_lock);
14801491

1481-
mnt = vfs_kern_mount(&nfsd_fs_type, SB_KERNMOUNT, "nfsd", NULL);
1482-
if (IS_ERR(mnt)) {
1483-
retval = PTR_ERR(mnt);
1484-
goto out_mount_err;
1485-
}
1486-
nn->nfsd_mnt = mnt;
14871492
return 0;
14881493

1489-
out_mount_err:
1490-
nfsd_reply_cache_shutdown(nn);
14911494
out_drc_error:
14921495
nfsd_idmap_shutdown(net);
14931496
out_idmap_error:
@@ -1500,7 +1503,6 @@ static __net_exit void nfsd_exit_net(struct net *net)
15001503
{
15011504
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
15021505

1503-
mntput(nn->nfsd_mnt);
15041506
nfsd_reply_cache_shutdown(nn);
15051507
nfsd_idmap_shutdown(net);
15061508
nfsd_export_shutdown(net);

fs/nfsd/nfsd.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ void nfsd_destroy(struct net *net);
9090

9191
bool i_am_nfsd(void);
9292

93+
int get_nfsdfs(struct net *);
94+
9395
struct nfsdfs_client {
9496
struct kref cl_ref;
9597
void (*cl_release)(struct kref *kref);
@@ -100,6 +102,7 @@ struct dentry *nfsd_client_mkdir(struct nfsd_net *nn,
100102
struct nfsdfs_client *ncl, u32 id, const struct tree_descr *);
101103
void nfsd_client_rmdir(struct dentry *dentry);
102104

105+
103106
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
104107
#ifdef CONFIG_NFSD_V2_ACL
105108
extern const struct svc_version nfsd_acl_version2;

0 commit comments

Comments
 (0)