From f46bdea12e223fab1845715dc8bfa1295d40c0f1 Mon Sep 17 00:00:00 2001 From: Dai Ngo Date: Fri, 23 Dec 2022 11:42:01 +0000 Subject: [PATCH] NFSD: fix WARN_ON_ONCE in __queue_delayed_work Currently nfsd4_state_shrinker_worker can be schduled multiple times from nfsd4_state_shrinker_count when memory is low. This causes the WARN_ON_ONCE in __queue_delayed_work to trigger. In this case, since __queue_delayed_work is called from kswapd and WARN_ON_ONCE resulted in the call to printk which might try to allocate memory which can cause deadlock. Fix by adding a flag to indicate whether nfsd4_state_shrinker_worker is active and skip calling mod_delayed_work from nfsd4_state_shrinker_count. Signed-off-by: Dai Ngo --- fs/nfsd/netns.h | 1 + fs/nfsd/nfs4state.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 8c854ba3285b..801d70926442 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h @@ -196,6 +196,7 @@ struct nfsd_net { atomic_t nfsd_courtesy_clients; struct shrinker nfsd_client_shrinker; struct delayed_work nfsd_shrinker_work; + bool nfsd_shrinker_active; }; /* Simple check to find out if a given net was properly initialized */ diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index e1e85c21f12b..52f99be15ba2 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4407,11 +4407,15 @@ nfsd4_state_shrinker_count(struct shrinker *shrink, struct shrink_control *sc) struct nfsd_net *nn = container_of(shrink, struct nfsd_net, nfsd_client_shrinker); + if (nn->nfsd_shrinker_active) + return 0; count = atomic_read(&nn->nfsd_courtesy_clients); if (!count) count = atomic_long_read(&num_delegations); - if (count) + if (count) { + nn->nfsd_shrinker_active = true; mod_delayed_work(laundry_wq, &nn->nfsd_shrinker_work, 0); + } return (unsigned long)count; } @@ -6249,6 +6253,7 @@ nfsd4_state_shrinker_worker(struct work_struct *work) courtesy_client_reaper(nn); deleg_reaper(nn); + nn->nfsd_shrinker_active = 0; } static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stid *stp) -- 2.9.5