nfscl: Fix setting of mtime for the NFSv4.n client

It was reported on freebsd-fs@ that unrolling a tarball
failed to set the correct modify time if delegations
were being issued.

This patch fixes the problem.

This bug only affects NFSv4 mounts where delegations
are being issued.  Not running the nfscbd or disabling
delegations on the NFSv4 server avoids the problem.

Reported by:	Peter Much <pmc@citylink.dinoex.sub.org>
Tested by:	Peter Much <pmc@citylink.dinoex.sub.org>
MFC after:	3 days
This commit is contained in:
Rick Macklem 2025-02-24 12:58:27 -08:00
parent 7c3c8605d6
commit b616d997cb
3 changed files with 9 additions and 4 deletions

View file

@ -626,7 +626,7 @@ int nfscl_renamedeleg(vnode_t, nfsv4stateid_t *, int *, vnode_t,
nfsv4stateid_t *, int *, NFSPROC_T *);
void nfscl_reclaimnode(vnode_t);
void nfscl_newnode(vnode_t);
void nfscl_delegmodtime(vnode_t);
void nfscl_delegmodtime(struct vnode *, struct timespec *);
void nfscl_deleggetmodtime(vnode_t, struct timespec *);
int nfscl_trydelegreturn(struct nfscldeleg *, struct ucred *,
struct nfsmount *, NFSPROC_T *);

View file

@ -5174,7 +5174,7 @@ nfscl_newnode(vnode_t vp)
* to the local clock time.
*/
void
nfscl_delegmodtime(vnode_t vp)
nfscl_delegmodtime(struct vnode *vp, struct timespec *mtime)
{
struct nfsclclient *clp;
struct nfscldeleg *dp;
@ -5198,7 +5198,10 @@ nfscl_delegmodtime(vnode_t vp)
}
dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
if (dp != NULL && (dp->nfsdl_flags & NFSCLDL_WRITE)) {
nanotime(&dp->nfsdl_modtime);
if (mtime != NULL)
dp->nfsdl_modtime = *mtime;
else
nanotime(&dp->nfsdl_modtime);
dp->nfsdl_flags |= NFSCLDL_MODTIMESET;
}
NFSUNLOCKCLSTATE();

View file

@ -1120,7 +1120,7 @@ nfs_setattr(struct vop_setattr_args *ap)
* Call nfscl_delegmodtime() to set the modify time
* locally, as required.
*/
nfscl_delegmodtime(vp);
nfscl_delegmodtime(vp, NULL);
} else
NFSUNLOCKNODE(np);
/*
@ -1158,6 +1158,8 @@ nfs_setattr(struct vop_setattr_args *ap)
NFSUNLOCKNODE(np);
}
}
if (vap->va_mtime.tv_sec != VNOVAL && error == 0)
nfscl_delegmodtime(vp, &vap->va_mtime);
return (error);
}