From b616d997cb48eaafe13069eecd95f0495b2358eb Mon Sep 17 00:00:00 2001 From: Rick Macklem Date: Mon, 24 Feb 2025 12:58:27 -0800 Subject: [PATCH] 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 Tested by: Peter Much MFC after: 3 days --- sys/fs/nfs/nfs_var.h | 2 +- sys/fs/nfsclient/nfs_clstate.c | 7 +++++-- sys/fs/nfsclient/nfs_clvnops.c | 4 +++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index b48d853b285..a95d9245c09 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -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 *); diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c index 7d1aab75362..adfb68f5d8f 100644 --- a/sys/fs/nfsclient/nfs_clstate.c +++ b/sys/fs/nfsclient/nfs_clstate.c @@ -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(); diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index bf24a161b94..a0bb781e5e5 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -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); }