git: 5971781ee78b - stable/13 - nfsd: Make the pNFS server update Change for Setxattr/Rmxattr
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 16 Nov 2022 20:10:45 UTC
The branch stable/13 has been updated by rmacklem:
URL: https://cgit.FreeBSD.org/src/commit/?id=5971781ee78b0c5879c2696437b1f7629d140c30
commit 5971781ee78b0c5879c2696437b1f7629d140c30
Author: Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2022-10-18 22:47:07 +0000
Commit: Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2022-11-16 20:09:33 +0000
nfsd: Make the pNFS server update Change for Setxattr/Rmxattr
When the NFS server does the Setxattr or Rmxattr operation,
the Change attribute (va_filerev) needs to be updated.
Without this patch, that was not happening for the
pNFS server configuration. This patch does a Setattr
against the DS file to make the Change attribute
change.
This bug was discovered during a recent IETF NFSv4 testing
event, where the Change attribute wasn't changed in the
operation reply.
(cherry picked from commit ae7816576e44412a8ae9daa92c210a6ba4f269dc)
---
sys/fs/nfsserver/nfs_nfsdport.c | 49 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 258642bb1060..51c4d59e5380 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -101,6 +101,7 @@ struct callout nfsd_callout;
static int nfssvc_srvcall(struct thread *, struct nfssvc_args *,
struct ucred *);
+static void nfsvno_updateds(struct vnode *, struct ucred *, struct thread *);
int nfsrv_enable_crossmntpt = 1;
static int nfs_commit_blks;
@@ -6568,8 +6569,11 @@ nfsvno_setxattr(struct vnode *vp, char *name, int len, struct mbuf *m,
if (error == 0) {
error = VOP_SETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, uiop,
cred, p);
- if (error == 0)
+ if (error == 0) {
+ if (vp->v_type == VREG && nfsrv_devidcnt != 0)
+ nfsvno_updateds(vp, cred, p);
error = VOP_FSYNC(vp, MNT_WAIT, p);
+ }
free(iv, M_TEMP);
}
@@ -6578,6 +6582,44 @@ out:
return (error);
}
+/*
+ * For a pNFS server, the DS file's ctime and
+ * va_filerev (TimeMetadata and Change) needs to
+ * be updated. This is a hack, but works by
+ * flipping the S_ISGID bit in va_mode and then
+ * flipping it back.
+ * It does result in two MDS->DS RPCs, but creating
+ * a custom RPC just to do this seems overkill, since
+ * Setxattr/Rmxattr will not be done that frequently.
+ * If it fails part way through, that is not too
+ * serious, since the DS file is never executed.
+ */
+static void
+nfsvno_updateds(struct vnode *vp, struct ucred *cred, NFSPROC_T *p)
+{
+ struct nfsvattr nva;
+ int ret;
+ u_short tmode;
+
+ ret = VOP_GETATTR(vp, &nva.na_vattr, cred);
+ if (ret == 0) {
+ tmode = nva.na_mode;
+ NFSVNO_ATTRINIT(&nva);
+ tmode ^= S_ISGID;
+ NFSVNO_SETATTRVAL(&nva, mode, tmode);
+ ret = nfsrv_proxyds(vp, 0, 0, cred, p,
+ NFSPROC_SETATTR, NULL, NULL, NULL, &nva,
+ NULL, NULL, 0, NULL);
+ if (ret == 0) {
+ tmode ^= S_ISGID;
+ NFSVNO_SETATTRVAL(&nva, mode, tmode);
+ ret = nfsrv_proxyds(vp, 0, 0, cred, p,
+ NFSPROC_SETATTR, NULL, NULL, NULL,
+ &nva, NULL, NULL, 0, NULL);
+ }
+ }
+}
+
/*
* Remove Extended attribute vnode op.
*/
@@ -6605,8 +6647,11 @@ nfsvno_rmxattr(struct nfsrv_descript *nd, struct vnode *vp, char *name,
if (error == EOPNOTSUPP)
error = VOP_SETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
cred, p);
- if (error == 0)
+ if (error == 0) {
+ if (vp->v_type == VREG && nfsrv_devidcnt != 0)
+ nfsvno_updateds(vp, cred, p);
error = VOP_FSYNC(vp, MNT_WAIT, p);
+ }
out:
NFSEXITCODE(error);
return (error);