From: Trond Myklebust Date: Sat, 29 Jan 2022 18:32:45 +0000 (-0500) Subject: NFSv4: Protect the state recovery thread against direct reclaim X-Git-Tag: v4.19.238~49 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2724d7743bb7df345feb7e4f88ecee97f0416d65;p=thirdparty%2Fkernel%2Fstable.git NFSv4: Protect the state recovery thread against direct reclaim [ Upstream commit 3e17898aca293a24dae757a440a50aa63ca29671 ] If memory allocation triggers a direct reclaim from the state recovery thread, then we can deadlock. Use memalloc_nofs_save/restore to ensure that doesn't happen. Signed-off-by: Trond Myklebust Signed-off-by: Sasha Levin --- diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 9c98547fcefcc..30576a10a1f4c 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -49,6 +49,7 @@ #include #include #include +#include #include @@ -2505,9 +2506,17 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp) static void nfs4_state_manager(struct nfs_client *clp) { + unsigned int memflags; int status = 0; const char *section = "", *section_sep = ""; + /* + * State recovery can deadlock if the direct reclaim code tries + * start NFS writeback. So ensure memory allocations are all + * GFP_NOFS. + */ + memflags = memalloc_nofs_save(); + /* Ensure exclusive access to NFSv4 state */ do { clear_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); @@ -2600,6 +2609,7 @@ static void nfs4_state_manager(struct nfs_client *clp) goto out_error; } + memalloc_nofs_restore(memflags); nfs4_end_drain_session(clp); nfs4_clear_state_manager_bit(clp); @@ -2616,6 +2626,7 @@ static void nfs4_state_manager(struct nfs_client *clp) return; if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) return; + memflags = memalloc_nofs_save(); } while (refcount_read(&clp->cl_count) > 1 && !signalled()); goto out_drain; @@ -2627,6 +2638,7 @@ out_error: clp->cl_hostname, -status); ssleep(1); out_drain: + memalloc_nofs_restore(memflags); nfs4_end_drain_session(clp); nfs4_clear_state_manager_bit(clp); }