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 v1] NFSD: Do not regrow a slot in the SEQUENCE that retired it
Date: Sun, 1 Nov 2026 10:47:42 -0500 [thread overview]
Message-ID: <20261101154742.1950822-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.
The slot is retired and rebuilt inside one request, so a client with a
request outstanding on it never sees NFS4ERR_BADSLOT. A copy 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 request whose reply was lost
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>
---
fs/nfsd/nfs4state.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index cafdf80f32de..1b8fe62cc756 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,14 @@ 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.
+ *
+ * A slot rebuilt in the call that retired it carries
+ * no cached reply for its outstanding request, so a
+ * retransmit of that request is executed again or fails
+ * with SEQ_MISORDERED instead of BADSLOT.
*/
- 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-01 15:47 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-01 15:47 Chuck Lever [this message]
2026-11-01 21:29 ` [PATCH v1] NFSD: Do not regrow a slot in the SEQUENCE that retired it NeilBrown
2026-11-02 0:59 ` Chuck Lever
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=20261101154742.1950822-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.