]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/6.6.26/nfsd-hold-a-lighter-weight-client-reference-over-cb_.patch
Linux 6.6.26
[thirdparty/kernel/stable-queue.git] / releases / 6.6.26 / nfsd-hold-a-lighter-weight-client-reference-over-cb_.patch
CommitLineData
ea78042b
SL
1From 087f54e85c2f0f44ad0049777df34351b6980d9d Mon Sep 17 00:00:00 2001
2From: Sasha Levin <sashal@kernel.org>
3Date: Fri, 5 Apr 2024 13:56:18 -0400
4Subject: nfsd: hold a lighter-weight client reference over CB_RECALL_ANY
5
6From: Jeff Layton <jlayton@kernel.org>
7
8[ Upstream commit 10396f4df8b75ff6ab0aa2cd74296565466f2c8d ]
9
10Currently the CB_RECALL_ANY job takes a cl_rpc_users reference to the
11client. While a callback job is technically an RPC that counter is
12really more for client-driven RPCs, and this has the effect of
13preventing the client from being unhashed until the callback completes.
14
15If nfsd decides to send a CB_RECALL_ANY just as the client reboots, we
16can end up in a situation where the callback can't complete on the (now
17dead) callback channel, but the new client can't connect because the old
18client can't be unhashed. This usually manifests as a NFS4ERR_DELAY
19return on the CREATE_SESSION operation.
20
21The job is only holding a reference to the client so it can clear a flag
22after the RPC completes. Fix this by having CB_RECALL_ANY instead hold a
23reference to the cl_nfsdfs.cl_ref. Typically we only take that sort of
24reference when dealing with the nfsdfs info files, but it should work
25appropriately here to ensure that the nfs4_client doesn't disappear.
26
27Fixes: 44df6f439a17 ("NFSD: add delegation reaper to react to low memory condition")
28Reported-by: Vladimir Benes <vbenes@redhat.com>
29Signed-off-by: Jeff Layton <jlayton@kernel.org>
30Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
31Signed-off-by: Sasha Levin <sashal@kernel.org>
32---
33 fs/nfsd/nfs4state.c | 7 ++-----
34 1 file changed, 2 insertions(+), 5 deletions(-)
35
36diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
37index 522596060252f..c7e52d980cd75 100644
38--- a/fs/nfsd/nfs4state.c
39+++ b/fs/nfsd/nfs4state.c
40@@ -2886,12 +2886,9 @@ static void
41 nfsd4_cb_recall_any_release(struct nfsd4_callback *cb)
42 {
43 struct nfs4_client *clp = cb->cb_clp;
44- struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
45
46- spin_lock(&nn->client_lock);
47 clear_bit(NFSD4_CLIENT_CB_RECALL_ANY, &clp->cl_flags);
48- put_client_renew_locked(clp);
49- spin_unlock(&nn->client_lock);
50+ drop_client(clp);
51 }
52
53 static const struct nfsd4_callback_ops nfsd4_cb_recall_any_ops = {
54@@ -6273,7 +6270,7 @@ deleg_reaper(struct nfsd_net *nn)
55 list_add(&clp->cl_ra_cblist, &cblist);
56
57 /* release in nfsd4_cb_recall_any_release */
58- atomic_inc(&clp->cl_rpc_users);
59+ kref_get(&clp->cl_nfsdfs.cl_ref);
60 set_bit(NFSD4_CLIENT_CB_RECALL_ANY, &clp->cl_flags);
61 clp->cl_ra_time = ktime_get_boottime_seconds();
62 }
63--
642.43.0
65