mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 14:04:54 +02:00
NFSv4: Protect the state recovery thread against direct reclaim
[ Upstream commit 3e17898aca ]
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 <trond.myklebust@hammerspace.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
9b9feec97c
commit
4a2544ce24
|
|
@ -49,6 +49,7 @@
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/sched/mm.h>
|
||||||
|
|
||||||
#include <linux/sunrpc/clnt.h>
|
#include <linux/sunrpc/clnt.h>
|
||||||
|
|
||||||
|
|
@ -2557,9 +2558,17 @@ static void nfs4_layoutreturn_any_run(struct nfs_client *clp)
|
||||||
|
|
||||||
static void nfs4_state_manager(struct nfs_client *clp)
|
static void nfs4_state_manager(struct nfs_client *clp)
|
||||||
{
|
{
|
||||||
|
unsigned int memflags;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
const char *section = "", *section_sep = "";
|
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 */
|
/* Ensure exclusive access to NFSv4 state */
|
||||||
do {
|
do {
|
||||||
trace_nfs4_state_mgr(clp);
|
trace_nfs4_state_mgr(clp);
|
||||||
|
|
@ -2654,6 +2663,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
|
||||||
clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
|
clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memalloc_nofs_restore(memflags);
|
||||||
nfs4_end_drain_session(clp);
|
nfs4_end_drain_session(clp);
|
||||||
nfs4_clear_state_manager_bit(clp);
|
nfs4_clear_state_manager_bit(clp);
|
||||||
|
|
||||||
|
|
@ -2671,6 +2681,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
|
||||||
return;
|
return;
|
||||||
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
|
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
|
||||||
return;
|
return;
|
||||||
|
memflags = memalloc_nofs_save();
|
||||||
} while (refcount_read(&clp->cl_count) > 1 && !signalled());
|
} while (refcount_read(&clp->cl_count) > 1 && !signalled());
|
||||||
goto out_drain;
|
goto out_drain;
|
||||||
|
|
||||||
|
|
@ -2683,6 +2694,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
|
||||||
clp->cl_hostname, -status);
|
clp->cl_hostname, -status);
|
||||||
ssleep(1);
|
ssleep(1);
|
||||||
out_drain:
|
out_drain:
|
||||||
|
memalloc_nofs_restore(memflags);
|
||||||
nfs4_end_drain_session(clp);
|
nfs4_end_drain_session(clp);
|
||||||
nfs4_clear_state_manager_bit(clp);
|
nfs4_clear_state_manager_bit(clp);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user