diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 7d64f211b05..1e215b52e83 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 ea8382e4282..c8c78d98be7 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) {