aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2026-01-08 16:27:32 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2026-01-08 16:27:32 +0000
commita6d57f312f18bbeeda8a34e99d0a662b0db9a190 (patch)
treeb908909c330a8468b80f2a77ccf30d2158bdd476
parent0aaa95ae02803ba0195c5da695ffbb17a79135bc (diff)
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c11
-rw-r--r--sys/fs/nfsserver/nfs_nfsdsubs.c38
2 files changed, 49 insertions, 0 deletions
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 7d64f211b058..1e215b52e835 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -1977,6 +1977,7 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
struct nfsexstuff nes;
struct thread *p = curthread;
uint32_t oldrepstat;
+ u_long savflags;
if (ndp->ni_vp == NULL) {
/*
@@ -1991,6 +1992,15 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
}
if (!nd->nd_repstat) {
if (ndp->ni_vp == NULL) {
+ /*
+ * Most file systems ignore va_flags for
+ * VOP_CREATE(), however setting va_flags
+ * for VOP_CREATE() causes problems for ZFS.
+ * So disable them and let nfsrv_fixattr()
+ * do them, as required.
+ */
+ savflags = nvap->na_flags;
+ nvap->na_flags = VNOVAL;
nd->nd_repstat = VOP_CREATE(ndp->ni_dvp,
&ndp->ni_vp, &ndp->ni_cnd, &nvap->na_vattr);
/* For a pNFS server, create the data file on a DS. */
@@ -2003,6 +2013,7 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
nfsrv_pnfscreate(ndp->ni_vp, &nvap->na_vattr,
cred, p);
}
+ nvap->na_flags = savflags;
VOP_VPUT_PAIR(ndp->ni_dvp, nd->nd_repstat == 0 ?
&ndp->ni_vp : NULL, false);
nfsvno_relpathbuf(ndp);
diff --git a/sys/fs/nfsserver/nfs_nfsdsubs.c b/sys/fs/nfsserver/nfs_nfsdsubs.c
index ea8382e4282a..c8c78d98be72 100644
--- a/sys/fs/nfsserver/nfs_nfsdsubs.c
+++ b/sys/fs/nfsserver/nfs_nfsdsubs.c
@@ -1697,6 +1697,44 @@ nfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp,
NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP);
}
}
+
+ /*
+ * For archive, ZFS sets it by default for new files,
+ * so if specified, it must be set or cleared.
+ * For hidden and system, no file system sets them
+ * by default upon creation, so they only need to be
+ * set and not cleared.
+ */
+ if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ARCHIVE)) {
+ if (nva.na_flags == VNOVAL)
+ nva.na_flags = 0;
+ if ((nvap->na_flags & UF_ARCHIVE) != 0)
+ nva.na_flags |= UF_ARCHIVE;
+ change++;
+ NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_ARCHIVE);
+ }
+ if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_HIDDEN)) {
+ if ((nvap->na_flags & UF_HIDDEN) != 0) {
+ if (nva.na_flags == VNOVAL)
+ nva.na_flags = 0;
+ nva.na_flags |= UF_HIDDEN;
+ change++;
+ NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_HIDDEN);
+ } else {
+ NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_HIDDEN);
+ }
+ }
+ if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SYSTEM)) {
+ if ((nvap->na_flags & UF_SYSTEM) != 0) {
+ if (nva.na_flags == VNOVAL)
+ nva.na_flags = 0;
+ nva.na_flags |= UF_SYSTEM;
+ change++;
+ NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_SYSTEM);
+ } else {
+ NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_SYSTEM);
+ }
+ }
if (change) {
error = nfsvno_setattr(vp, &nva, nd->nd_cred, p, exp);
if (error) {