Skip to content

Commit f385f7d

Browse files
daimngochucklever
authored andcommitted
NFSD: register/unregister of nfsd-client shrinker at nfsd startup/shutdown time
Currently the nfsd-client shrinker is registered and unregistered at the time the nfsd module is loaded and unloaded. The problem with this is the shrinker is being registered before all of the relevant fields in nfsd_net are initialized when nfsd is started. This can lead to an oops when memory is low and the shrinker is called while nfsd is not running. This patch moves the register/unregister of nfsd-client shrinker from module load/unload time to nfsd startup/shutdown time. Fixes: 44df6f4 ("NFSD: add delegation reaper to react to low memory condition") Reported-by: Mike Galbraith <efault@gmx.de> Signed-off-by: Dai Ngo <dai.ngo@oracle.com> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent e6cf91b commit f385f7d

File tree

3 files changed

+14
-21
lines changed

3 files changed

+14
-21
lines changed

fs/nfsd/nfs4state.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4421,7 +4421,7 @@ nfsd4_state_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
44214421
return SHRINK_STOP;
44224422
}
44234423

4424-
int
4424+
void
44254425
nfsd4_init_leases_net(struct nfsd_net *nn)
44264426
{
44274427
struct sysinfo si;
@@ -4443,16 +4443,6 @@ nfsd4_init_leases_net(struct nfsd_net *nn)
44434443
nn->nfs4_max_clients = max_t(int, max_clients, NFS4_CLIENTS_PER_GB);
44444444

44454445
atomic_set(&nn->nfsd_courtesy_clients, 0);
4446-
nn->nfsd_client_shrinker.scan_objects = nfsd4_state_shrinker_scan;
4447-
nn->nfsd_client_shrinker.count_objects = nfsd4_state_shrinker_count;
4448-
nn->nfsd_client_shrinker.seeks = DEFAULT_SEEKS;
4449-
return register_shrinker(&nn->nfsd_client_shrinker, "nfsd-client");
4450-
}
4451-
4452-
void
4453-
nfsd4_leases_net_shutdown(struct nfsd_net *nn)
4454-
{
4455-
unregister_shrinker(&nn->nfsd_client_shrinker);
44564446
}
44574447

44584448
static void init_nfs4_replay(struct nfs4_replay *rp)
@@ -8069,8 +8059,17 @@ static int nfs4_state_create_net(struct net *net)
80698059
INIT_DELAYED_WORK(&nn->nfsd_shrinker_work, nfsd4_state_shrinker_worker);
80708060
get_net(net);
80718061

8062+
nn->nfsd_client_shrinker.scan_objects = nfsd4_state_shrinker_scan;
8063+
nn->nfsd_client_shrinker.count_objects = nfsd4_state_shrinker_count;
8064+
nn->nfsd_client_shrinker.seeks = DEFAULT_SEEKS;
8065+
8066+
if (register_shrinker(&nn->nfsd_client_shrinker, "nfsd-client"))
8067+
goto err_shrinker;
80728068
return 0;
80738069

8070+
err_shrinker:
8071+
put_net(net);
8072+
kfree(nn->sessionid_hashtbl);
80748073
err_sessionid:
80758074
kfree(nn->unconf_id_hashtbl);
80768075
err_unconf_id:
@@ -8163,6 +8162,7 @@ nfs4_state_shutdown_net(struct net *net)
81638162
struct list_head *pos, *next, reaplist;
81648163
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
81658164

8165+
unregister_shrinker(&nn->nfsd_client_shrinker);
81668166
cancel_delayed_work_sync(&nn->laundromat_work);
81678167
locks_end_grace(&nn->nfsd4_manager);
81688168

fs/nfsd/nfsctl.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,9 +1457,7 @@ static __net_init int nfsd_init_net(struct net *net)
14571457
goto out_idmap_error;
14581458
nn->nfsd_versions = NULL;
14591459
nn->nfsd4_minorversions = NULL;
1460-
retval = nfsd4_init_leases_net(nn);
1461-
if (retval)
1462-
goto out_drc_error;
1460+
nfsd4_init_leases_net(nn);
14631461
retval = nfsd_reply_cache_init(nn);
14641462
if (retval)
14651463
goto out_cache_error;
@@ -1469,8 +1467,6 @@ static __net_init int nfsd_init_net(struct net *net)
14691467
return 0;
14701468

14711469
out_cache_error:
1472-
nfsd4_leases_net_shutdown(nn);
1473-
out_drc_error:
14741470
nfsd_idmap_shutdown(net);
14751471
out_idmap_error:
14761472
nfsd_export_shutdown(net);
@@ -1486,7 +1482,6 @@ static __net_exit void nfsd_exit_net(struct net *net)
14861482
nfsd_idmap_shutdown(net);
14871483
nfsd_export_shutdown(net);
14881484
nfsd_netns_free_versions(net_generic(net, nfsd_net_id));
1489-
nfsd4_leases_net_shutdown(nn);
14901485
}
14911486

14921487
static struct pernet_operations nfsd_net_ops = {

fs/nfsd/nfsd.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -504,17 +504,15 @@ extern void unregister_cld_notifier(void);
504504
extern void nfsd4_ssc_init_umount_work(struct nfsd_net *nn);
505505
#endif
506506

507-
extern int nfsd4_init_leases_net(struct nfsd_net *nn);
508-
extern void nfsd4_leases_net_shutdown(struct nfsd_net *nn);
507+
extern void nfsd4_init_leases_net(struct nfsd_net *nn);
509508

510509
#else /* CONFIG_NFSD_V4 */
511510
static inline int nfsd4_is_junction(struct dentry *dentry)
512511
{
513512
return 0;
514513
}
515514

516-
static inline int nfsd4_init_leases_net(struct nfsd_net *nn) { return 0; };
517-
static inline void nfsd4_leases_net_shutdown(struct nfsd_net *nn) {};
515+
static inline void nfsd4_init_leases_net(struct nfsd_net *nn) { };
518516

519517
#define register_cld_notifier() 0
520518
#define unregister_cld_notifier() do { } while(0)

0 commit comments

Comments
 (0)