|
NeilBrown |
a4e4f7 |
From: Trond Myklebust <trond.myklebust@hammerspace.com>
|
|
NeilBrown |
a4e4f7 |
Date: Sat, 29 Jan 2022 13:32:45 -0500
|
|
NeilBrown |
a4e4f7 |
Subject: [PATCH] NFSv4: Protect the state recovery thread against direct
|
|
NeilBrown |
a4e4f7 |
reclaim
|
|
NeilBrown |
a4e4f7 |
Git-commit: 3e17898aca293a24dae757a440a50aa63ca29671
|
|
NeilBrown |
a4e4f7 |
Patch-mainline: v5.18
|
|
NeilBrown |
a4e4f7 |
References: git-fixes
|
|
NeilBrown |
a4e4f7 |
|
|
NeilBrown |
a4e4f7 |
If memory allocation triggers a direct reclaim from the state recovery
|
|
NeilBrown |
a4e4f7 |
thread, then we can deadlock. Use memalloc_nofs_save/restore to ensure
|
|
NeilBrown |
a4e4f7 |
that doesn't happen.
|
|
NeilBrown |
a4e4f7 |
|
|
NeilBrown |
a4e4f7 |
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
|
|
NeilBrown |
a4e4f7 |
Acked-by: NeilBrown <neilb@suse.com>
|
|
NeilBrown |
a4e4f7 |
|
|
NeilBrown |
a4e4f7 |
---
|
|
NeilBrown |
a4e4f7 |
fs/nfs/nfs4state.c | 12 ++++++++++++
|
|
NeilBrown |
a4e4f7 |
1 file changed, 12 insertions(+)
|
|
NeilBrown |
a4e4f7 |
|
|
NeilBrown |
a4e4f7 |
--- a/fs/nfs/nfs4state.c
|
|
NeilBrown |
a4e4f7 |
+++ b/fs/nfs/nfs4state.c
|
|
NeilBrown |
a4e4f7 |
@@ -49,6 +49,7 @@
|
|
NeilBrown |
a4e4f7 |
#include <linux/workqueue.h>
|
|
NeilBrown |
a4e4f7 |
#include <linux/bitops.h>
|
|
NeilBrown |
a4e4f7 |
#include <linux/jiffies.h>
|
|
NeilBrown |
a4e4f7 |
+#include <linux/sched/mm.h>
|
|
NeilBrown |
a4e4f7 |
|
|
NeilBrown |
a4e4f7 |
#include <linux/sunrpc/clnt.h>
|
|
NeilBrown |
a4e4f7 |
|
|
NeilBrown |
a4e4f7 |
@@ -2576,9 +2577,17 @@ static void nfs4_layoutreturn_any_run(st
|
|
NeilBrown |
a4e4f7 |
|
|
NeilBrown |
a4e4f7 |
static void nfs4_state_manager(struct nfs_client *clp)
|
|
NeilBrown |
a4e4f7 |
{
|
|
NeilBrown |
a4e4f7 |
+ unsigned int memflags;
|
|
NeilBrown |
a4e4f7 |
int status = 0;
|
|
NeilBrown |
a4e4f7 |
const char *section = "", *section_sep = "";
|
|
NeilBrown |
a4e4f7 |
|
|
NeilBrown |
a4e4f7 |
+ /*
|
|
NeilBrown |
a4e4f7 |
+ * State recovery can deadlock if the direct reclaim code tries
|
|
NeilBrown |
a4e4f7 |
+ * start NFS writeback. So ensure memory allocations are all
|
|
NeilBrown |
a4e4f7 |
+ * GFP_NOFS.
|
|
NeilBrown |
a4e4f7 |
+ */
|
|
NeilBrown |
a4e4f7 |
+ memflags = memalloc_nofs_save();
|
|
NeilBrown |
a4e4f7 |
+
|
|
NeilBrown |
a4e4f7 |
/* Ensure exclusive access to NFSv4 state */
|
|
NeilBrown |
a4e4f7 |
do {
|
|
NeilBrown |
a4e4f7 |
trace_nfs4_state_mgr(clp);
|
|
NeilBrown |
a4e4f7 |
@@ -2673,6 +2682,7 @@ static void nfs4_state_manager(struct nf
|
|
NeilBrown |
a4e4f7 |
clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
|
|
NeilBrown |
a4e4f7 |
}
|
|
NeilBrown |
a4e4f7 |
|
|
NeilBrown |
a4e4f7 |
+ memalloc_nofs_restore(memflags);
|
|
NeilBrown |
a4e4f7 |
nfs4_end_drain_session(clp);
|
|
NeilBrown |
a4e4f7 |
nfs4_clear_state_manager_bit(clp);
|
|
NeilBrown |
a4e4f7 |
|
|
NeilBrown |
a4e4f7 |
@@ -2690,6 +2700,7 @@ static void nfs4_state_manager(struct nf
|
|
NeilBrown |
a4e4f7 |
return;
|
|
NeilBrown |
a4e4f7 |
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
|
|
NeilBrown |
a4e4f7 |
return;
|
|
NeilBrown |
a4e4f7 |
+ memflags = memalloc_nofs_save();
|
|
NeilBrown |
a4e4f7 |
} while (refcount_read(&clp->cl_count) > 1 && !signalled());
|
|
NeilBrown |
a4e4f7 |
goto out_drain;
|
|
NeilBrown |
a4e4f7 |
|
|
NeilBrown |
a4e4f7 |
@@ -2702,6 +2713,7 @@ out_error:
|
|
NeilBrown |
a4e4f7 |
clp->cl_hostname, -status);
|
|
NeilBrown |
a4e4f7 |
ssleep(1);
|
|
NeilBrown |
a4e4f7 |
out_drain:
|
|
NeilBrown |
a4e4f7 |
+ memalloc_nofs_restore(memflags);
|
|
NeilBrown |
a4e4f7 |
nfs4_end_drain_session(clp);
|
|
NeilBrown |
a4e4f7 |
nfs4_clear_state_manager_bit(clp);
|
|
NeilBrown |
a4e4f7 |
}
|