Author: rmacklem
Date: Fri May  3 02:58:33 2019
New Revision: 347044
URL: https://svnweb.freebsd.org/changeset/base/347044

Log:
  MFC: r346424
  Add support for the ModeSetMasked attribute to the NFSv4.1 server.
  
  I do not know of an extant NFSv4.1 client that currently does a Setattr
  operation for the ModeSetMasked, but it has been discussed on the linux-nfs
  mailing list.
  This patch adds support for doing a Setattr of ModeSetMasked, so that it
  will work for any future NFSv4.1 client that chooses to do so.
  Tested via a hacked FreeBSD NFSv4.1 client.

Modified:
  stable/12/sys/fs/nfs/nfsproto.h
  stable/12/sys/fs/nfsserver/nfs_nfsdport.c
  stable/12/sys/fs/nfsserver/nfs_nfsdserv.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/fs/nfs/nfsproto.h
==============================================================================
--- stable/12/sys/fs/nfs/nfsproto.h     Fri May  3 02:55:54 2019        
(r347043)
+++ stable/12/sys/fs/nfs/nfsproto.h     Fri May  3 02:58:33 2019        
(r347044)
@@ -1090,7 +1090,7 @@ struct nfsv3_sattr {
  */
 #define        NFSATTRBIT_SUPPSETONLY1  (NFSATTRBM_TIMEACCESSSET |             
\
                                 NFSATTRBM_TIMEMODIFYSET)
-#define        NFSATTRBIT_SUPPSETONLY2 0
+#define        NFSATTRBIT_SUPPSETONLY2 (NFSATTRBM_MODESETMASKED)
 
 /*
  * NFSATTRBIT_SETABLE - SETABLE0 - bits 0<->31
@@ -1106,7 +1106,8 @@ struct nfsv3_sattr {
        NFSATTRBM_OWNERGROUP |                                          \
        NFSATTRBM_TIMEACCESSSET |                                       \
        NFSATTRBM_TIMEMODIFYSET)
-#define        NFSATTRBIT_SETABLE2             0
+#define        NFSATTRBIT_SETABLE2                                             
\
+       (NFSATTRBM_MODESETMASKED)
 
 /*
  * NFSATTRBIT_NFSV41 - Attributes only supported by NFSv4.1.

Modified: stable/12/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- stable/12/sys/fs/nfsserver/nfs_nfsdport.c   Fri May  3 02:55:54 2019        
(r347043)
+++ stable/12/sys/fs/nfsserver/nfs_nfsdport.c   Fri May  3 02:58:33 2019        
(r347044)
@@ -2696,10 +2696,12 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, str
        int attrsum = 0;
        int i, j;
        int error, attrsize, bitpos, aclsize, aceerr, retnotsup = 0;
-       int toclient = 0;
+       int moderet, toclient = 0;
        u_char *cp, namestr[NFSV4_SMALLSTR + 1];
        uid_t uid;
        gid_t gid;
+       u_short mode, mask;             /* Same type as va_mode. */
+       struct vattr va;
 
        error = nfsrv_getattrbits(nd, attrbitp, NULL, &retnotsup);
        if (error)
@@ -2717,6 +2719,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, str
        } else {
                bitpos = 0;
        }
+       moderet = 0;
        for (; bitpos < NFSATTRBIT_MAX; bitpos++) {
            if (attrsum > attrsize) {
                error = NFSERR_BADXDR;
@@ -2766,6 +2769,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, str
                        attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(i));
                        break;
                case NFSATTRBIT_MODE:
+                       moderet = NFSERR_INVAL; /* Can't do MODESETMASKED. */
                        NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
                        nvap->na_mode = nfstov_mode(*tl);
                        attrsum += NFSX_UNSIGNED;
@@ -2868,6 +2872,32 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, str
                            if (!toclient)
                                nvap->na_vaflags |= VA_UTIMES_NULL;
                        }
+                       break;
+               case NFSATTRBIT_MODESETMASKED:
+                       NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+                       mode = fxdr_unsigned(u_short, *tl++);
+                       mask = fxdr_unsigned(u_short, *tl);
+                       /*
+                        * vp == NULL implies an Open/Create operation.
+                        * This attribute can only be used for Setattr and
+                        * only for NFSv4.1 or higher.
+                        * If moderet != 0, a mode attribute has also been
+                        * specified and this attribute cannot be done in the
+                        * same Setattr operation.
+                        */
+                       if ((nd->nd_flag & ND_NFSV41) == 0)
+                               nd->nd_repstat = NFSERR_ATTRNOTSUPP;
+                       else if ((mode & ~07777) != 0 || (mask & ~07777) != 0 ||
+                           vp == NULL)
+                               nd->nd_repstat = NFSERR_INVAL;
+                       else if (moderet == 0)
+                               moderet = VOP_GETATTR(vp, &va, nd->nd_cred);
+                       if (moderet == 0)
+                               nvap->na_mode = (mode & mask) |
+                                   (va.va_mode & ~mask);
+                       else
+                               nd->nd_repstat = moderet;
+                       attrsum += 2 * NFSX_UNSIGNED;
                        break;
                default:
                        nd->nd_repstat = NFSERR_ATTRNOTSUPP;

Modified: stable/12/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- stable/12/sys/fs/nfsserver/nfs_nfsdserv.c   Fri May  3 02:55:54 2019        
(r347043)
+++ stable/12/sys/fs/nfsserver/nfs_nfsdserv.c   Fri May  3 02:58:33 2019        
(r347044)
@@ -461,13 +461,18 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int
                }
            }
            if (!nd->nd_repstat &&
-               NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE)) {
+               (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE) ||
+                NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODESETMASKED))) {
                NFSVNO_ATTRINIT(&nva2);
                NFSVNO_SETATTRVAL(&nva2, mode, nva.na_mode);
                nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
                    exp);
-               if (!nd->nd_repstat)
-                   NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODE);
+               if (!nd->nd_repstat) {
+                   if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE))
+                       NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODE);
+                   if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODESETMASKED))
+                       NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODESETMASKED);
+               }
            }
 
 #ifdef NFS4_ACL_EXTATTR_NAME
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to