From: Chuck Lever <cel@kernel.org>
To: NeilBrown <neilb@ownmail.net>, Jeff Layton <jlayton@kernel.org>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <dai.ngo@oracle.com>, Tom Talpey <tom@talpey.com>
Cc: <linux-nfs@vger.kernel.org>
Subject: [PATCH v2] NFSD: Do not regrow a slot in the SEQUENCE that retired it
Date: Sun, 1 Nov 2026 20:10:47 -0500 [thread overview]
Message-ID: <20261102011047.2659441-1-cel@kernel.org> (raw)
When a SEQUENCE acknowledges a smaller slot table, free_session_slots()
retires the slots above the target. If that SEQUENCE is on the new top
slot, the growth test later in the same nfsd4_sequence() call finds the
table at its target and allocates back the slot the call just freed.
A client fills in sa_highest_slotid from the slots in use when it
builds a request, so a request it sends afterward on a higher slot can
reach NFSD first. When the reply to that request is lost, the
acknowledging SEQUENCE retires and rebuilds the slot inside one
request, and the client's retransmit never sees NFS4ERR_BADSLOT. A
retransmit of the slot's first request passes the seqid 1 rule for a
rebuilt slot and executes a second time. A CREATE replayed this way
returns NFS4ERR_EXIST, reproduced with pynfs against a two-slot session
and one write to drop_caches. A retransmit of a later request matches
the retained seqid on the uninitialized rebuilt slot and gets
NFS4ERR_SEQ_MISORDERED, which the Linux client retries every 15 seconds
without limit.
Skip the growth block in a call that retired slots. A retransmit that
arrives while the slot is retired now gets NFS4ERR_BADSLOT, which the
Linux client handles as a session reset. The next request on the top
live slot still grows the table on demand, so a copy delayed past that
request meets a rebuilt slot as before.
Fixes: fc8738c68d0b ("nfsd: add support for freeing unused session-DRC slots")
Signed-off-by: Chuck Lever <cel@kernel.org>
---
Changes in v2:
- Explain the request in flight on the retired slot (per Neil's review)
- Rewrite the comment on the growth test (per Neil's review)
- Link to v1: https://lore.kernel.org/r/20261101154742.1950822-1-cel@kernel.org
fs/nfsd/nfs4state.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index cafdf80f32de..8b7483278f50 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -5230,6 +5230,7 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfs4_client *clp;
struct nfsd4_slot *slot;
struct nfsd4_conn *conn;
+ bool retired = false;
__be32 status;
int buflen;
u32 maxlen, respsize;
@@ -5301,9 +5302,11 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
slot->sl_generation == session->se_slot_gen &&
seq->maxslots <= session->se_target_maxslots &&
seq->slotid < session->se_target_maxslots &&
- !nfsd4_slots_inuse(session, session->se_target_maxslots))
+ !nfsd4_slots_inuse(session, session->se_target_maxslots)) {
/* Client acknowledged our reduce maxreqs */
free_session_slots(session, session->se_target_maxslots);
+ retired = true;
+ }
buflen = (seq->cachethis) ?
session->se_fchannel.maxresp_cached :
@@ -5360,8 +5363,15 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
* configured maximum, not the running thread count, so a
* client resuming from idle can grow back before the pool
* scales up.
+ *
+ * Do not grow the table in the call that retired slots. A
+ * rebuilt slot has no cached reply, so a retransmit on it
+ * is executed again or fails with SEQ_MISORDERED. Left
+ * retired, the slot returns BADSLOT, which the client
+ * recovers from.
*/
- if (seq->slotid == session->se_fchannel.maxreqs - 1 &&
+ if (!retired &&
+ seq->slotid == session->se_fchannel.maxreqs - 1 &&
session->se_target_maxslots >= session->se_fchannel.maxreqs) {
int s = session->se_fchannel.maxreqs;
int ceiling = min_t(int, NFSD_MAX_SLOTS_PER_SESSION,
--
2.54.0
next reply other threads:[~2026-11-02 1:10 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-02 1:10 Chuck Lever [this message]
2026-11-02 12:18 ` [PATCH v2] NFSD: Do not regrow a slot in the SEQUENCE that retired it Jeff Layton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261102011047.2659441-1-cel@kernel.org \
--to=cel@kernel.org \
--cc=dai.ngo@oracle.com \
--cc=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neilb@ownmail.net \
--cc=okorniev@redhat.com \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.