nfs_clstate.c: Handle the same stateid case correctly

When an NFSv4.1/4.2 sarver upgrades a read delegation to
a write delegation, it does not need to change the
delegation's stateid.

Without this patch, a DELEGRETURN of the stateid was done
for the case where the delegation stateid had not changed.
This return was bogus, since the delegation stateid now
represents the new write delegation.

This patch fixes the priblem by checking for "same stateid"
and only doing the DELEGRETURN when it is not the same.

PR:	289711
Tested by:	Peter Much <[email protected]_sub.org>
MFC after:	2 weeks
This commit is contained in:
Rick Macklem committed 2026-03-08 14:09:36 -07:00
1 parent 164bddf01b
commit 016570c446
1 file changed
+7 -1
+7 -1
View File
@@ -433,9 +433,11 @@ nfscl_deleg(mount_t mp, struct nfsclclient *clp, u_int8_t *nfhp,
{
struct nfscldeleg *tdp;
struct nfsmount *nmp;
bool trydelegret;
KASSERT(mp != NULL, ("nfscl_deleg: mp NULL"));
nmp = VFSTONFS(mp);
trydelegret = false;
/*
* Since a delegation might be added to the mount,
@@ -467,6 +469,9 @@ nfscl_deleg(mount_t mp, struct nfsclclient *clp, u_int8_t *nfhp,
* Read delegation. Otherwise, return the new delegation.
*/
if (dp != NULL) {
if (NFSBCMP(dp->nfsdl_stateid.other,
tdp->nfsdl_stateid.other, NFSX_STATEIDOTHER))
trydelegret = true;
if ((dp->nfsdl_flags & NFSCLDL_WRITE) != 0 &&
(tdp->nfsdl_flags & NFSCLDL_READ) != 0) {
TAILQ_REMOVE(&clp->nfsc_deleg, tdp, nfsdl_list);
@@ -485,7 +490,8 @@ nfscl_deleg(mount_t mp, struct nfsclclient *clp, u_int8_t *nfhp,
}
NFSUNLOCKCLSTATE();
if (tdp != NULL) {
nfscl_trydelegreturn(tdp, cred, nmp, p);
if (trydelegret)
nfscl_trydelegreturn(tdp, cred, nmp, p);
free(tdp, M_NFSCLDELEG);
}
return (0);