* [PATCH v4 0/2] nfsd: CB_SEQUENCE error handling fixes and cleanups
@ 2025-02-07 13:45 Jeff Layton
2025-02-07 13:45 ` [PATCH v4 1/2] nfsd: overhaul CB_SEQUENCE error handling Jeff Layton
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Jeff Layton @ 2025-02-07 13:45 UTC (permalink / raw)
To: Chuck Lever, Neil Brown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
J. Bruce Fields
Cc: linux-nfs, linux-kernel, Jeff Layton
Bruce convinced me that the single-threadedness of the workqueue and the
fact that the RPCs are killed synchronously was enough to ensure that
the session can't disappear out from under a running callback. Given
that, I'm breaking these patches out into a separate series that can
potentially be backported.
I think this rework makes sense, and I've run these against pynfs,
fstests, and nfstest, but I'm not sure how well that stresses the
backchannel error handling. I'd like to put this into linux-next for now
and see if any problems arise.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
Changes in v4:
- Hold back on session refcounting changes for now and just send CB_SEQUENCE
error handling rework.
- Link to v3: https://lore.kernel.org/r/20250129-nfsd-6-14-v3-0-506e71e39e6b@kernel.org
Changes in v3:
- rename cb_session_changed to nfsd4_cb_session_changed
- rename restart_callback to requeue_callback, and rename need_restart:
label to requeue:
- don't increment seq_nr on -ESERVERFAULT
- comment cleanups
- drop client-side rpc patch (will send separately)
- Link to v2: https://lore.kernel.org/r/20250129-nfsd-6-14-v2-0-2700c92f3e44@kernel.org
Changes in v2:
- make nfsd4_session be RCU-freed
- change code to keep reference to session over callback RPCs
- rework error handling in nfsd4_cb_sequence_done()
- move NFSv4.0 handling out of nfsd4_cb_sequence_done()
- Link to v1: https://lore.kernel.org/r/20250123-nfsd-6-14-v1-0-c1137a4fa2ae@kernel.org
---
Jeff Layton (2):
nfsd: overhaul CB_SEQUENCE error handling
nfsd: lift NFSv4.0 handling out of nfsd4_cb_sequence_done()
fs/nfsd/nfs4callback.c | 107 ++++++++++++++++++++++++++++++-------------------
1 file changed, 66 insertions(+), 41 deletions(-)
---
base-commit: 50934b1a613cabba2b917879c3e722882b72f628
change-id: 20250123-nfsd-6-14-b0797e385dc0
Best regards,
--
Jeff Layton <jlayton@kernel.org>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 1/2] nfsd: overhaul CB_SEQUENCE error handling
2025-02-07 13:45 [PATCH v4 0/2] nfsd: CB_SEQUENCE error handling fixes and cleanups Jeff Layton
@ 2025-02-07 13:45 ` Jeff Layton
2025-02-07 13:45 ` [PATCH v4 2/2] nfsd: lift NFSv4.0 handling out of nfsd4_cb_sequence_done() Jeff Layton
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Jeff Layton @ 2025-02-07 13:45 UTC (permalink / raw)
To: Chuck Lever, Neil Brown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
J. Bruce Fields
Cc: linux-nfs, linux-kernel, Jeff Layton
Some of the existing error handling in nfsd4_cb_sequence_done is
incorrect. For instance, if a NFS4ERR_SEQ_MISORDERED or NFS4ERR_BADSLOT
status races with rpc_clnt teardown, then the callback could be dropped
on the floor and never resent. This patch first does some general cleanup
and then reworks most of the error handling cases from first principles:
There is only one case where we want to proceed with processing the rest
of the CB_COMPOUND, and that's when the cb_seq_status is 0. Make the
default return value be false, and only set it to true in that case.
Rename the "need_restart" label to "requeue", to better indicate that
it's being requeued to the workqueue.
When the callback isn't going to be requeued or restarted, don't bother
checking RPC_SIGNALLED(). That should only be checked when we intend to
restart an rpc_task.
For -ESERVERFAULT, don't increment the sequence number since it's
possible the sessionid didn't match. Mark the backchannel bad and wait
for it to be recreated.
For NFS4ERR_DELAY, test for RPC_SIGNALLED() first, since that's an
indication that the client is being torn down. Requeue it in that case.
When restarting the RPC (but not the entire callback), test
RPC_SIGNALLED(). If it has been, then fall through to restart the
callback instead of just restarting the RPC.
For NFS4ERR_BADSLOT, mark the backchannel faulty and leak the slot so
that it can't be reused.
For NFS4ERR_SEQ_MISORDERED, retry once with seq_nr of 1, and if that
fails, handle it like BADSLOT.
When requeuing a callback, always release the slot in case there
have been changes to the slot table or session in the interim when it's
resubmitted.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
fs/nfsd/nfs4callback.c | 64 +++++++++++++++++++++++++++++++++-----------------
1 file changed, 43 insertions(+), 21 deletions(-)
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index cf6d29828f4e561418b812ea2c9402929dd52bd0..a8603c3cdcdafbf9ccc6296425112f1730419b7b 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -1332,7 +1332,7 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
{
struct nfs4_client *clp = cb->cb_clp;
struct nfsd4_session *session = clp->cl_cb_session;
- bool ret = true;
+ bool ret = false;
if (!clp->cl_minorversion) {
/*
@@ -1345,13 +1345,13 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
* handle that case here.
*/
if (RPC_SIGNALLED(task))
- goto need_restart;
+ goto requeue;
return true;
}
if (cb->cb_held_slot < 0)
- goto need_restart;
+ goto requeue;
/* This is the operation status code for CB_SEQUENCE */
trace_nfsd_cb_seq_status(task, cb);
@@ -1365,11 +1365,15 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
* (sequence ID, cached reply) MUST NOT change.
*/
++session->se_cb_seq_nr[cb->cb_held_slot];
+ ret = true;
break;
case -ESERVERFAULT:
- ++session->se_cb_seq_nr[cb->cb_held_slot];
+ /*
+ * Call succeeded, but CB_SEQUENCE reply failed sanity checks.
+ * The client has gone insane. Mark the BC faulty, since there
+ * isn't much else we can do.
+ */
nfsd4_mark_cb_fault(cb->cb_clp);
- ret = false;
break;
case 1:
/*
@@ -1380,39 +1384,57 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
*/
fallthrough;
case -NFS4ERR_BADSESSION:
+ /* Mark the backchannel faulty. Restart the call. */
nfsd4_mark_cb_fault(cb->cb_clp);
- ret = false;
- goto need_restart;
+ goto requeue;
case -NFS4ERR_DELAY:
+ /*
+ * If the rpc_clnt is being torn down, then we must restart
+ * the call from scratch.
+ */
+ if (RPC_SIGNALLED(task))
+ goto requeue;
cb->cb_seq_status = 1;
- if (!rpc_restart_call(task))
- goto out;
-
+ rpc_restart_call(task);
rpc_delay(task, 2 * HZ);
return false;
- case -NFS4ERR_BADSLOT:
- goto retry_nowait;
case -NFS4ERR_SEQ_MISORDERED:
+ /*
+ * Reattempt once with seq_nr 1. If that fails, treat this
+ * like BADSLOT.
+ */
if (session->se_cb_seq_nr[cb->cb_held_slot] != 1) {
session->se_cb_seq_nr[cb->cb_held_slot] = 1;
goto retry_nowait;
}
- break;
+ fallthrough;
+ case -NFS4ERR_BADSLOT:
+ /*
+ * BADSLOT means that the client and server are out of sync
+ * on the BC parameters. In this case, we want to mark the
+ * backchannel faulty and then try it again, but _leak_ the
+ * slot so no one uses it.
+ */
+ nfsd4_mark_cb_fault(cb->cb_clp);
+ cb->cb_held_slot = -1;
+ goto retry_nowait;
default:
nfsd4_mark_cb_fault(cb->cb_clp);
}
trace_nfsd_cb_free_slot(task, cb);
nfsd41_cb_release_slot(cb);
-
- if (RPC_SIGNALLED(task))
- goto need_restart;
-out:
return ret;
retry_nowait:
- if (rpc_restart_call_prepare(task))
- ret = false;
- goto out;
-need_restart:
+ /*
+ * RPC_SIGNALLED() means that the rpc_client is being torn down and
+ * (possibly) recreated. Restart the call completely in that case.
+ */
+ if (!RPC_SIGNALLED(task)) {
+ rpc_restart_call_prepare(task);
+ return false;
+ }
+requeue:
+ nfsd41_cb_release_slot(cb);
if (!test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags)) {
trace_nfsd_cb_restart(clp, cb);
task->tk_status = 0;
--
2.48.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 2/2] nfsd: lift NFSv4.0 handling out of nfsd4_cb_sequence_done()
2025-02-07 13:45 [PATCH v4 0/2] nfsd: CB_SEQUENCE error handling fixes and cleanups Jeff Layton
2025-02-07 13:45 ` [PATCH v4 1/2] nfsd: overhaul CB_SEQUENCE error handling Jeff Layton
@ 2025-02-07 13:45 ` Jeff Layton
2025-02-07 13:58 ` [PATCH v4 0/2] nfsd: CB_SEQUENCE error handling fixes and cleanups J. Bruce Fields
2025-02-07 15:08 ` Chuck Lever
3 siblings, 0 replies; 5+ messages in thread
From: Jeff Layton @ 2025-02-07 13:45 UTC (permalink / raw)
To: Chuck Lever, Neil Brown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
J. Bruce Fields
Cc: linux-nfs, linux-kernel, Jeff Layton
It's a bit strange to call nfsd4_cb_sequence_done() on a callback with no
CB_SEQUENCE. Lift the handling of restarting a call into a new helper,
and move the handling of NFSv4.0 into nfsd4_cb_done().
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
fs/nfsd/nfs4callback.c | 53 ++++++++++++++++++++++++++------------------------
1 file changed, 28 insertions(+), 25 deletions(-)
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index a8603c3cdcdafbf9ccc6296425112f1730419b7b..570762d992c553987923669d57b4ab8f529655d3 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -1328,27 +1328,22 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
rpc_call_start(task);
}
-static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback *cb)
+static void requeue_callback(struct rpc_task *task, struct nfsd4_callback *cb)
{
struct nfs4_client *clp = cb->cb_clp;
- struct nfsd4_session *session = clp->cl_cb_session;
- bool ret = false;
- if (!clp->cl_minorversion) {
- /*
- * If the backchannel connection was shut down while this
- * task was queued, we need to resubmit it after setting up
- * a new backchannel connection.
- *
- * Note that if we lost our callback connection permanently
- * the submission code will error out, so we don't need to
- * handle that case here.
- */
- if (RPC_SIGNALLED(task))
- goto requeue;
-
- return true;
+ nfsd41_cb_release_slot(cb);
+ if (!test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags)) {
+ trace_nfsd_cb_restart(clp, cb);
+ task->tk_status = 0;
+ cb->cb_need_restart = true;
}
+}
+
+static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback *cb)
+{
+ struct nfsd4_session *session = cb->cb_clp->cl_cb_session;
+ bool ret = false;
if (cb->cb_held_slot < 0)
goto requeue;
@@ -1427,19 +1422,14 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
retry_nowait:
/*
* RPC_SIGNALLED() means that the rpc_client is being torn down and
- * (possibly) recreated. Restart the call completely in that case.
+ * (possibly) recreated. Restart the whole callback in that case.
*/
if (!RPC_SIGNALLED(task)) {
rpc_restart_call_prepare(task);
return false;
}
requeue:
- nfsd41_cb_release_slot(cb);
- if (!test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags)) {
- trace_nfsd_cb_restart(clp, cb);
- task->tk_status = 0;
- cb->cb_need_restart = true;
- }
+ requeue_callback(task, cb);
return false;
}
@@ -1450,8 +1440,21 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
trace_nfsd_cb_rpc_done(clp);
- if (!nfsd4_cb_sequence_done(task, cb))
+ if (!clp->cl_minorversion) {
+ /*
+ * If the backchannel connection was shut down while this
+ * task was queued, we need to resubmit it after setting up
+ * a new backchannel connection.
+ *
+ * Note that if we lost our callback connection permanently
+ * the submission code will error out, so we don't need to
+ * handle that case here.
+ */
+ if (RPC_SIGNALLED(task))
+ requeue_callback(task, cb);
+ } else if (!nfsd4_cb_sequence_done(task, cb)) {
return;
+ }
if (cb->cb_status) {
WARN_ONCE(task->tk_status,
--
2.48.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v4 0/2] nfsd: CB_SEQUENCE error handling fixes and cleanups
2025-02-07 13:45 [PATCH v4 0/2] nfsd: CB_SEQUENCE error handling fixes and cleanups Jeff Layton
2025-02-07 13:45 ` [PATCH v4 1/2] nfsd: overhaul CB_SEQUENCE error handling Jeff Layton
2025-02-07 13:45 ` [PATCH v4 2/2] nfsd: lift NFSv4.0 handling out of nfsd4_cb_sequence_done() Jeff Layton
@ 2025-02-07 13:58 ` J. Bruce Fields
2025-02-07 15:08 ` Chuck Lever
3 siblings, 0 replies; 5+ messages in thread
From: J. Bruce Fields @ 2025-02-07 13:58 UTC (permalink / raw)
To: Jeff Layton
Cc: Chuck Lever, Neil Brown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
linux-nfs, linux-kernel
On Fri, Feb 07, 2025 at 08:45:02AM -0500, Jeff Layton wrote:
> I think this rework makes sense, and I've run these against pynfs,
> fstests, and nfstest, but I'm not sure how well that stresses the
> backchannel error handling.
Very little to none at all, unfortunately, I'd guess.
pynfs/nfs4.1/server41tests/st_trunking.py had some ideas for some simple
tests, maybe that'd be one starting point. Or maybe
server41tests/st_delegation.py
--b.
> I'd like to put this into linux-next for now
> and see if any problems arise.
>
> Signed-off-by: Jeff Layton <jlayton@kernel.org>
> ---
> Changes in v4:
> - Hold back on session refcounting changes for now and just send CB_SEQUENCE
> error handling rework.
> - Link to v3: https://lore.kernel.org/r/20250129-nfsd-6-14-v3-0-506e71e39e6b@kernel.org
>
> Changes in v3:
> - rename cb_session_changed to nfsd4_cb_session_changed
> - rename restart_callback to requeue_callback, and rename need_restart:
> label to requeue:
> - don't increment seq_nr on -ESERVERFAULT
> - comment cleanups
> - drop client-side rpc patch (will send separately)
> - Link to v2: https://lore.kernel.org/r/20250129-nfsd-6-14-v2-0-2700c92f3e44@kernel.org
>
> Changes in v2:
> - make nfsd4_session be RCU-freed
> - change code to keep reference to session over callback RPCs
> - rework error handling in nfsd4_cb_sequence_done()
> - move NFSv4.0 handling out of nfsd4_cb_sequence_done()
> - Link to v1: https://lore.kernel.org/r/20250123-nfsd-6-14-v1-0-c1137a4fa2ae@kernel.org
>
> ---
> Jeff Layton (2):
> nfsd: overhaul CB_SEQUENCE error handling
> nfsd: lift NFSv4.0 handling out of nfsd4_cb_sequence_done()
>
> fs/nfsd/nfs4callback.c | 107 ++++++++++++++++++++++++++++++-------------------
> 1 file changed, 66 insertions(+), 41 deletions(-)
> ---
> base-commit: 50934b1a613cabba2b917879c3e722882b72f628
> change-id: 20250123-nfsd-6-14-b0797e385dc0
>
> Best regards,
> --
> Jeff Layton <jlayton@kernel.org>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v4 0/2] nfsd: CB_SEQUENCE error handling fixes and cleanups
2025-02-07 13:45 [PATCH v4 0/2] nfsd: CB_SEQUENCE error handling fixes and cleanups Jeff Layton
` (2 preceding siblings ...)
2025-02-07 13:58 ` [PATCH v4 0/2] nfsd: CB_SEQUENCE error handling fixes and cleanups J. Bruce Fields
@ 2025-02-07 15:08 ` Chuck Lever
3 siblings, 0 replies; 5+ messages in thread
From: Chuck Lever @ 2025-02-07 15:08 UTC (permalink / raw)
To: Jeff Layton, Neil Brown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
J. Bruce Fields
Cc: linux-nfs, linux-kernel
On 2/7/25 8:45 AM, Jeff Layton wrote:
> Bruce convinced me that the single-threadedness of the workqueue and the
> fact that the RPCs are killed synchronously was enough to ensure that
> the session can't disappear out from under a running callback. Given
> that, I'm breaking these patches out into a separate series that can
> potentially be backported.
>
> I think this rework makes sense, and I've run these against pynfs,
> fstests, and nfstest, but I'm not sure how well that stresses the
> backchannel error handling. I'd like to put this into linux-next for now
> and see if any problems arise.
I'm good with the proposed code changes. A couple of general comments:
- I plan to put these changes in nfsd-testing first to get some local
NFS testing experience under our belts before exposing them to the
broader community of testers.
- nfsd-testing is not automatically merged with linux-next or fs-next.
These changes would not appear in linux-next until I move them to
nfsd-next.
- I prefer having the first patch broken into smaller changes to give
bisection a little more leverage. Eg, the "restart:" and
"bool = false" changes are fine in a single patch, but change the
recovery actions for each status code in separate patches, maybe?
> Signed-off-by: Jeff Layton <jlayton@kernel.org>
> ---
> Changes in v4:
> - Hold back on session refcounting changes for now and just send CB_SEQUENCE
> error handling rework.
> - Link to v3: https://lore.kernel.org/r/20250129-nfsd-6-14-v3-0-506e71e39e6b@kernel.org
>
> Changes in v3:
> - rename cb_session_changed to nfsd4_cb_session_changed
> - rename restart_callback to requeue_callback, and rename need_restart:
> label to requeue:
> - don't increment seq_nr on -ESERVERFAULT
> - comment cleanups
> - drop client-side rpc patch (will send separately)
> - Link to v2: https://lore.kernel.org/r/20250129-nfsd-6-14-v2-0-2700c92f3e44@kernel.org
>
> Changes in v2:
> - make nfsd4_session be RCU-freed
> - change code to keep reference to session over callback RPCs
> - rework error handling in nfsd4_cb_sequence_done()
> - move NFSv4.0 handling out of nfsd4_cb_sequence_done()
> - Link to v1: https://lore.kernel.org/r/20250123-nfsd-6-14-v1-0-c1137a4fa2ae@kernel.org
>
> ---
> Jeff Layton (2):
> nfsd: overhaul CB_SEQUENCE error handling
> nfsd: lift NFSv4.0 handling out of nfsd4_cb_sequence_done()
>
> fs/nfsd/nfs4callback.c | 107 ++++++++++++++++++++++++++++++-------------------
> 1 file changed, 66 insertions(+), 41 deletions(-)
> ---
> base-commit: 50934b1a613cabba2b917879c3e722882b72f628
> change-id: 20250123-nfsd-6-14-b0797e385dc0
>
> Best regards,
--
Chuck Lever
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-02-07 15:08 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-07 13:45 [PATCH v4 0/2] nfsd: CB_SEQUENCE error handling fixes and cleanups Jeff Layton
2025-02-07 13:45 ` [PATCH v4 1/2] nfsd: overhaul CB_SEQUENCE error handling Jeff Layton
2025-02-07 13:45 ` [PATCH v4 2/2] nfsd: lift NFSv4.0 handling out of nfsd4_cb_sequence_done() Jeff Layton
2025-02-07 13:58 ` [PATCH v4 0/2] nfsd: CB_SEQUENCE error handling fixes and cleanups J. Bruce Fields
2025-02-07 15:08 ` Chuck Lever
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®