diff options
| author | Jeff Layton <jlayton@kernel.org> | 2026-06-11 16:01:04 -0400 |
|---|---|---|
| committer | Chuck Lever <cel@kernel.org> | 2026-07-05 21:07:22 -0400 |
| commit | 06da7b592dad2b7065ebcf7f71b051ab95155035 (patch) | |
| tree | 550c9b31502c830be047ad70f7fda529be55898b | |
| parent | fb95299207c8adb0502c061fe466927d2e1595c0 (diff) | |
| download | linux-next-06da7b592dad2b7065ebcf7f71b051ab95155035.tar.gz linux-next-06da7b592dad2b7065ebcf7f71b051ab95155035.zip | |
nfsd: drop the stateid, not the stateowner, on seqid_op replay retry
In nfs4_preprocess_seqid_op() the stateid is obtained from
nfsd4_lookup_stateid(), which holds a reference on the nfs4_stid
(sc_count) but takes no reference on the stateowner. openlockstateid()
merely casts that stid and likewise takes no reference.
When nfsd4_cstate_assign_replay() returns -EAGAIN (the replay owner is
being torn down, RP_UNHASHED) it has not taken a stateowner reference on
that path. The error handling nevertheless called
nfs4_put_stateowner(stp->st_stateowner), dropping an so_count reference
the function never acquired -- risking a stateowner refcount underflow and
use-after-free -- while leaking the sc_count reference held on the stid.
The leaked stid reference can also stall a concurrent
nfsd4_close_open_stateid() waiting for sc_count to drop.
Drop the reference actually held -- the stid -- before retrying. The
stateowner stays alive through the reference held by the stid. This mirrors
the open path in nfsd4_process_open1(), where the put balances a reference
that path explicitly holds on the stateowner.
Fixes: eec762080008 ("nfsd: replace rp_mutex to avoid deadlock in move_to_close_lru()")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260611-nfsd-testing-v2-21-5b90e276f2d9@kernel.org
Signed-off-by: Chuck Lever <cel@kernel.org>
| -rw-r--r-- | fs/nfsd/nfs4state.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index a0c97bff3cff..bef0ec9be459 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -7876,7 +7876,7 @@ retry: return status; stp = openlockstateid(s); if (nfsd4_cstate_assign_replay(cstate, stp->st_stateowner) == -EAGAIN) { - nfs4_put_stateowner(stp->st_stateowner); + nfs4_put_stid(&stp->st_stid); goto retry; } |
