summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2023-02-08 15:45:38 +1100
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2023-02-15 10:33:00 -0500
commit5bab56fff53ce161ed859d9559a10361d4f79578 (patch)
tree474bbfe300423da97f7957e5d35223f2b672b2e1 /net
parentd67307b4147e51b00545e2e17c20bd2cc8e6c745 (diff)
downloadlinux-stable-5bab56fff53ce161ed859d9559a10361d4f79578.tar.gz
linux-stable-5bab56fff53ce161ed859d9559a10361d4f79578.tar.bz2
linux-stable-5bab56fff53ce161ed859d9559a10361d4f79578.zip
NFS: fix disabling of swap
When swap is activated to a file on an NFSv4 mount we arrange that the state manager thread is always present as starting a new thread requires memory allocations that might block waiting for swap. Unfortunately the code for allowing the state manager thread to exit when swap is disabled was not tested properly and does not work. This can be seen by examining /proc/fs/nfsfs/servers after disabling swap and unmounting the filesystem. The servers file will still list one entry. Also a "ps" listing will show the state manager thread is still present. There are two problems. 1/ rpc_clnt_swap_deactivate() doesn't walk up the ->cl_parent list to find the primary client on which the state manager runs. 2/ The thread is not woken up properly and it immediately goes back to sleep without checking whether it is really needed. Using nfs4_schedule_state_manager() ensures a proper wake-up. Reported-by: Olga Kornievskaia <aglo@umich.edu> Fixes: 4dc73c679114 ("NFSv4: keep state manager thread active if swap is enabled") Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/clnt.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 0b0b9f1eed46..fd7e1c630493 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -3350,6 +3350,8 @@ rpc_clnt_swap_deactivate_callback(struct rpc_clnt *clnt,
void
rpc_clnt_swap_deactivate(struct rpc_clnt *clnt)
{
+ while (clnt != clnt->cl_parent)
+ clnt = clnt->cl_parent;
if (atomic_dec_if_positive(&clnt->cl_swapper) == 0)
rpc_clnt_iterate_for_each_xprt(clnt,
rpc_clnt_swap_deactivate_callback, NULL);