The branch stable/15 has been updated by rmacklem:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=3a64c667f16fbc3c1cedee081de895aa911be523

commit 3a64c667f16fbc3c1cedee081de895aa911be523
Author:     Rick Macklem <[email protected]>
AuthorDate: 2025-10-22 21:16:48 +0000
Commit:     Rick Macklem <[email protected]>
CommitDate: 2025-11-05 02:29:27 +0000

    nfs: Add support for the NFSv4 archive attribute
    
    The archive attribute (UF_ARCHIVE) is listed as deprecated
    in RFC8881.  However, the Windows NFSv4.1 client folk disagree
    with this and say they need support for it.
    
    This patch adds support for it, in a manner similar to what
    is done for UF_SYSTEM and UF_HIDDEN.
    
    (cherry picked from commit 3b6d4c6cdffd6e37b8fa6e0b0fe3067210582c9c)
---
 sys/fs/nfs/nfs_commonsubs.c     | 24 +++++++++++++++++++++---
 sys/fs/nfs/nfsproto.h           |  4 ++++
 sys/fs/nfsclient/nfs_clrpcops.c |  3 +++
 sys/fs/nfsclient/nfs_clvnops.c  |  8 ++++++--
 sys/fs/nfsserver/nfs_nfsdport.c | 11 +++++++----
 sys/fs/nfsserver/nfs_nfsdserv.c | 12 +++++++++++-
 6 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index abfec9edc485..8e1a26eef354 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -641,6 +641,7 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr 
*vap,
                if ((flags & NFSSATTR_FULL) && vap->va_size != VNOVAL)
                        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE);
                if ((flags & NFSSATTR_FULL) && vap->va_flags != VNOVAL) {
+                       NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ARCHIVE);
                        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN);
                        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM);
                }
@@ -1672,9 +1673,17 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
                        attrsum += NFSX_UNSIGNED;
                        break;
                case NFSATTRBIT_ARCHIVE:
-                       NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
-                       if (compare && !(*retcmpp))
-                               *retcmpp = NFSERR_ATTRNOTSUPP;
+                       NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+                       if (compare) {
+                               if (!(*retcmpp) && ((*tl == newnfs_true &&
+                                   (nap->na_flags & UF_ARCHIVE) == 0) ||
+                                   (*tl == newnfs_false &&
+                                    (nap->na_flags & UF_ARCHIVE) != 0)))
+                                       *retcmpp = NFSERR_NOTSAME;
+                       } else if (nap != NULL) {
+                               if (*tl == newnfs_true)
+                                       nap->na_flags |= UF_ARCHIVE;
+                       }
                        attrsum += NFSX_UNSIGNED;
                        break;
                case NFSATTRBIT_CANSETTIME:
@@ -2804,6 +2813,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount 
*mp, vnode_t vp,
                        if (!has_hiddensystem) {
                            NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN);
                            NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM);
+                           NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_ARCHIVE);
                        }
                        if (clone_blksize == 0)
                            NFSCLRBIT_ATTRBIT(&attrbits,
@@ -2888,6 +2898,14 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount 
*mp, vnode_t vp,
                        *tl = txdr_unsigned(NFSV4ACE_SUPTYPES);
                        retnum += NFSX_UNSIGNED;
                        break;
+               case NFSATTRBIT_ARCHIVE:
+                       NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+                       if ((vap->va_flags & UF_ARCHIVE) != 0)
+                               *tl = newnfs_true;
+                       else
+                               *tl = newnfs_false;
+                       retnum += NFSX_UNSIGNED;
+                       break;
                case NFSATTRBIT_CANSETTIME:
                        NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
                        if (fsinf.fs_properties & NFSV3FSINFO_CANSETTIME)
diff --git a/sys/fs/nfs/nfsproto.h b/sys/fs/nfs/nfsproto.h
index d628108bdc1a..13fec8a102a3 100644
--- a/sys/fs/nfs/nfsproto.h
+++ b/sys/fs/nfs/nfsproto.h
@@ -1135,6 +1135,7 @@ struct nfsv3_sattr {
        NFSATTRBM_RDATTRERROR |                                         \
        NFSATTRBM_ACL |                                                 \
        NFSATTRBM_ACLSUPPORT |                                          \
+       NFSATTRBM_ARCHIVE |                                             \
        NFSATTRBM_CANSETTIME |                                          \
        NFSATTRBM_CASEINSENSITIVE |                                     \
        NFSATTRBM_CASEPRESERVING |                                      \
@@ -1217,6 +1218,7 @@ struct nfsv3_sattr {
 #define        NFSATTRBIT_SETABLE0                                             
\
        (NFSATTRBM_SIZE |                                               \
        NFSATTRBM_HIDDEN |                                              \
+       NFSATTRBM_ARCHIVE |                                             \
        NFSATTRBM_ACL)
 #define        NFSATTRBIT_SETABLE1                                             
\
        (NFSATTRBM_MODE |                                               \
@@ -1262,6 +1264,7 @@ struct nfsv3_sattr {
        NFSATTRBM_CHANGE |                                              \
        NFSATTRBM_SIZE |                                                \
        NFSATTRBM_FSID |                                                \
+       NFSATTRBM_ARCHIVE |                                             \
        NFSATTRBM_FILEID |                                              \
        NFSATTRBM_HIDDEN |                                              \
        NFSATTRBM_MAXREAD)
@@ -1298,6 +1301,7 @@ struct nfsv3_sattr {
        NFSATTRBM_CHANGE |                                              \
        NFSATTRBM_SIZE |                                                \
        NFSATTRBM_FSID |                                                \
+       NFSATTRBM_ARCHIVE |                                             \
        NFSATTRBM_FILEID |                                              \
        NFSATTRBM_HIDDEN |                                              \
        NFSATTRBM_MAXREAD)
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index 544b1962de26..bad3e69ca5cf 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -4162,9 +4162,12 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, 
nfsuint64 *cookiep,
                    NFSATTRBIT_TIMECREATE))
                        NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMECREATE);
                if (!NFSISSET_ATTRBIT(&dnp->n_vattr.na_suppattr,
+                   NFSATTRBIT_ARCHIVE) ||
+                   !NFSISSET_ATTRBIT(&dnp->n_vattr.na_suppattr,
                    NFSATTRBIT_HIDDEN) ||
                    !NFSISSET_ATTRBIT(&dnp->n_vattr.na_suppattr,
                    NFSATTRBIT_SYSTEM)) {
+                       NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_ARCHIVE);
                        NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN);
                        NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM);
                }
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index eee571a04821..5ce764fcedea 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -1081,12 +1081,14 @@ nfs_setattr(struct vop_setattr_args *ap)
 #endif
 
        /*
-        * Only setting of UF_HIDDEN and UF_SYSTEM are supported and
+        * Only setting of UF_ARCHIVE, UF_HIDDEN and UF_SYSTEM are supported and
         * only for NFSv4 servers that support them.
         */
        nmp = VFSTONFS(vp->v_mount);
        if (vap->va_flags != VNOVAL && (!NFSHASNFSV4(nmp) ||
-           (vap->va_flags & ~(UF_HIDDEN | UF_SYSTEM)) != 0 ||
+           (vap->va_flags & ~(UF_ARCHIVE | UF_HIDDEN | UF_SYSTEM)) != 0 ||
+           ((vap->va_flags & UF_ARCHIVE) != 0 &&
+            !NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, NFSATTRBIT_ARCHIVE)) ||
            ((vap->va_flags & UF_HIDDEN) != 0 &&
             !NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, NFSATTRBIT_HIDDEN)) ||
            ((vap->va_flags & UF_SYSTEM) != 0 &&
@@ -4835,6 +4837,8 @@ nfs_pathconf(struct vop_pathconf_args *ap)
                break;
        case _PC_HAS_HIDDENSYSTEM:
                if (NFS_ISV4(vp) && NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr,
+                   NFSATTRBIT_ARCHIVE) &&
+                   NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr,
                    NFSATTRBIT_HIDDEN) &&
                    NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr,
                    NFSATTRBIT_SYSTEM))
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 5ba86314ead1..ff28b089da5d 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -3193,7 +3193,8 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, struct 
nfsvattr *nvap,
                bitpos = NFSATTRBIT_MAX;
        } else {
                bitpos = 0;
-               if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_HIDDEN) ||
+               if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ARCHIVE) ||
+                   NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_HIDDEN) ||
                    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SYSTEM))
                        nvap->na_flags = 0;
        }
@@ -3226,9 +3227,11 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, 
struct nfsvattr *nvap,
                        attrsum += aclsize;
                        break;
                case NFSATTRBIT_ARCHIVE:
-                       NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
-                       if (!nd->nd_repstat)
-                               nd->nd_repstat = NFSERR_ATTRNOTSUPP;
+                       NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+                       if (nd->nd_repstat == 0) {
+                               if (*tl == newnfs_true)
+                                       nvap->na_flags |= UF_ARCHIVE;
+                       }
                        attrsum += NFSX_UNSIGNED;
                        break;
                case NFSATTRBIT_HIDDEN:
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index 9dda65d5cbcf..217675173add 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -436,6 +436,7 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int 
isdgram,
 
        /* For NFSv4, only va_uid and va_flags is used from nva2. */
        NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNER);
+       NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_ARCHIVE);
        NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_HIDDEN);
        NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_SYSTEM);
        preat_ret = nfsvno_getattr(vp, &nva2, nd, p, 1, &retbits);
@@ -569,8 +570,15 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int 
isdgram,
                }
            }
            if (!nd->nd_repstat &&
-               (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN) ||
+               (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_ARCHIVE) ||
+                NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN) ||
                 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM))) {
+               if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_ARCHIVE)) {
+                   if ((nva.na_flags & UF_ARCHIVE) != 0)
+                       oldflags |= UF_ARCHIVE;
+                   else
+                       oldflags &= ~UF_ARCHIVE;
+               }
                if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN)) {
                    if ((nva.na_flags & UF_HIDDEN) != 0)
                        oldflags |= UF_HIDDEN;
@@ -588,6 +596,8 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int 
isdgram,
                nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
                    exp);
                if (!nd->nd_repstat) {
+                   if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_ARCHIVE))
+                       NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_ARCHIVE);
                    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN))
                        NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_HIDDEN);
                    if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM))

Reply via email to