Author: rmacklem
Date: Fri Nov 22 00:22:55 2019
New Revision: 354989
URL: https://svnweb.freebsd.org/changeset/base/354989

Log:
  Fix the pNFS server's reporting of SpaceUsed (va_bytes).
  
  The pNFS server currently reports SpaceUsed (va_bytes) for the metadata
  file. This in not correct, since the metadata file is always empty and,
  as such, va_bytes is just the allocation for the empty file.
  This patch adds va_bytes to the list of attributes acquired from the
  DS for a file, so that it includes the allocated data size and is updated
  when the file is written.
  For files created on a pNFS server before this patch is applied, the
  va_bytes value is estimated by rounding va_size up to a multiple of
  BLKDEV_IOSIZE. Once the file is written after this patch has been
  applied to the metadata server, the va_bytes returned for the file
  will be correct.
  
  This patch only affects a pNFS metadata server.
  
  Found during testing of the NFSv4.2 pNFS server for the Allocate operation.
  (Not yet in head/current.)
  
  MFC after:    2 weeks

Modified:
  head/sys/fs/nfs/nfsrvstate.h
  head/sys/fs/nfsserver/nfs_nfsdport.c

Modified: head/sys/fs/nfs/nfsrvstate.h
==============================================================================
--- head/sys/fs/nfs/nfsrvstate.h        Thu Nov 21 23:55:43 2019        
(r354988)
+++ head/sys/fs/nfs/nfsrvstate.h        Fri Nov 22 00:22:55 2019        
(r354989)
@@ -355,14 +355,24 @@ struct nfsdevice {
 };
 
 /*
- * This structure holds the va_size, va_filerev, va_atime and va_mtime for the
- * DS file and is stored in the metadata file's extended attribute 
pnfsd.dsattr.
+ * This structure holds the va_size, va_filerev, va_atime, va_mtime and
+ * va_bytes for the DS file and is stored in the metadata file's extended
+ * attribute pnfsd.dsattr.
+ * opnfsdsattr was missing the va_bytes field and, as such, it was updated.
  */
+struct opnfsdsattr {
+       uint64_t        dsa_filerev;
+       uint64_t        dsa_size;
+       struct timespec dsa_atime;
+       struct timespec dsa_mtime;
+};
+
 struct pnfsdsattr {
        uint64_t        dsa_filerev;
        uint64_t        dsa_size;
        struct timespec dsa_atime;
        struct timespec dsa_mtime;
+       uint64_t        dsa_bytes;
 };
 
 /*

Modified: head/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdport.c        Thu Nov 21 23:55:43 2019        
(r354988)
+++ head/sys/fs/nfsserver/nfs_nfsdport.c        Fri Nov 22 00:22:55 2019        
(r354989)
@@ -277,7 +277,8 @@ nfsvno_getattr(struct vnode *vp, struct nfsvattr *nvap
        }
 
        /*
-        * Acquire the Change, Size and TimeModify attributes, as required.
+        * Acquire the Change, Size, TimeAccess, TimeModify and SpaceUsed
+        * attributes, as required.
         * This needs to be done for regular files if:
         * - non-NFSv4 RPCs or
         * - when attrbitp == NULL or
@@ -292,7 +293,8 @@ nfsvno_getattr(struct vnode *vp, struct nfsvattr *nvap
            NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_CHANGE) ||
            NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE) ||
            NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEACCESS) ||
-           NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEMODIFY))) {
+           NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEMODIFY) ||
+           NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SPACEUSED))) {
                error = nfsrv_proxyds(vp, 0, 0, nd->nd_cred, p,
                    NFSPROC_GETATTR, NULL, NULL, NULL, &na, NULL);
                if (error == 0)
@@ -312,6 +314,7 @@ nfsvno_getattr(struct vnode *vp, struct nfsvattr *nvap
                nvap->na_mtime = na.na_mtime;
                nvap->na_filerev = na.na_filerev;
                nvap->na_size = na.na_size;
+               nvap->na_bytes = na.na_bytes;
        }
        NFSD_DEBUG(4, "nfsvno_getattr: gotattr=%d err=%d chg=%ju\n", gotattr,
            error, (uintmax_t)na.na_filerev);
@@ -3881,6 +3884,7 @@ nfsrv_dscreate(struct vnode *dvp, struct vattr *vap, s
                                        dsa->dsa_size = va.va_size;
                                        dsa->dsa_atime = va.va_atime;
                                        dsa->dsa_mtime = va.va_mtime;
+                                       dsa->dsa_bytes = va.va_bytes;
                                }
                        }
                        if (error == 0) {
@@ -4405,6 +4409,7 @@ nfsrv_proxyds(struct vnode *vp, off_t off, int cnt, st
        struct vnode *dvp[NFSDEV_MAXMIRRORS];
        struct nfsdevice *ds;
        struct pnfsdsattr dsattr;
+       struct opnfsdsattr odsattr;
        char *buf;
        int buflen, error, failpos, i, mirrorcnt, origmircnt, trycnt;
 
@@ -4429,15 +4434,31 @@ nfsrv_proxyds(struct vnode *vp, off_t off, int cnt, st
                error = vn_extattr_get(vp, IO_NODELOCKED,
                    EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsattr", &buflen, buf,
                    p);
-               if (error == 0 && buflen != sizeof(dsattr))
-                       error = ENXIO;
                if (error == 0) {
-                       NFSBCOPY(buf, &dsattr, buflen);
-                       nap->na_filerev = dsattr.dsa_filerev;
-                       nap->na_size = dsattr.dsa_size;
-                       nap->na_atime = dsattr.dsa_atime;
-                       nap->na_mtime = dsattr.dsa_mtime;
-
+                       if (buflen == sizeof(odsattr)) {
+                               NFSBCOPY(buf, &odsattr, buflen);
+                               nap->na_filerev = odsattr.dsa_filerev;
+                               nap->na_size = odsattr.dsa_size;
+                               nap->na_atime = odsattr.dsa_atime;
+                               nap->na_mtime = odsattr.dsa_mtime;
+                               /*
+                                * Fake na_bytes by rounding up na_size.
+                                * Since we don't know the block size, just
+                                * use BLKDEV_IOSIZE.
+                                */
+                               nap->na_bytes = (odsattr.dsa_size +
+                                   BLKDEV_IOSIZE - 1) & ~(BLKDEV_IOSIZE - 1);
+                       } else if (buflen == sizeof(dsattr)) {
+                               NFSBCOPY(buf, &dsattr, buflen);
+                               nap->na_filerev = dsattr.dsa_filerev;
+                               nap->na_size = dsattr.dsa_size;
+                               nap->na_atime = dsattr.dsa_atime;
+                               nap->na_mtime = dsattr.dsa_mtime;
+                               nap->na_bytes = dsattr.dsa_bytes;
+                       } else
+                               error = ENXIO;
+               }
+               if (error == 0) {
                        /*
                         * If nfsrv_pnfsgetdsattr is 0 or nfsrv_checkdsattr()
                         * returns 0, just return now.  nfsrv_checkdsattr()
@@ -4809,6 +4830,7 @@ nfsrv_setextattr(struct vnode *vp, struct nfsvattr *na
        dsattr.dsa_size = nap->na_size;
        dsattr.dsa_atime = nap->na_atime;
        dsattr.dsa_mtime = nap->na_mtime;
+       dsattr.dsa_bytes = nap->na_bytes;
        error = vn_extattr_set(vp, IO_NODELOCKED, EXTATTR_NAMESPACE_SYSTEM,
            "pnfsd.dsattr", sizeof(dsattr), (char *)&dsattr, p);
        if (error != 0)
@@ -4984,12 +5006,13 @@ nfsrv_writedsdorpc(struct nfsmount *nmp, fhandle_t *fh
        nd->nd_bpos = mtod(m, char *) + m->m_len;
        NFSD_DEBUG(4, "nfsrv_writedsdorpc: lastmb len=%d\n", m->m_len);
 
-       /* Do a Getattr for Size, Change and Modify Time. */
+       /* Do a Getattr for the attributes that change upon writing. */
        NFSZERO_ATTRBIT(&attrbits);
        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE);
        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESS);
        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY);
+       NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SPACEUSED);
        NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
        *tl = txdr_unsigned(NFSV4OP_GETATTR);
        (void) nfsrv_putattrbit(nd, &attrbits);
@@ -5168,12 +5191,13 @@ nfsrv_setattrdsdorpc(fhandle_t *fhp, struct ucred *cre
        nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID);
        nfscl_fillsattr(nd, &nap->na_vattr, vp, NFSSATTR_FULL, 0);
 
-       /* Do a Getattr for Size, Change, Access Time and Modify Time. */
+       /* Do a Getattr for the attributes that change due to writing. */
        NFSZERO_ATTRBIT(&attrbits);
        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE);
        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESS);
        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY);
+       NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SPACEUSED);
        NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
        *tl = txdr_unsigned(NFSV4OP_GETATTR);
        (void) nfsrv_putattrbit(nd, &attrbits);
@@ -5470,7 +5494,7 @@ nfsrv_setacldsrpc(fhandle_t *fhp, struct ucred *cred, 
 }
 
 /*
- * Getattr call to the DS for the Modify, Size and Change attributes.
+ * Getattr call to the DS for the attributes that change due to writing.
  */
 static int
 nfsrv_getattrdsrpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p,
@@ -5489,6 +5513,7 @@ nfsrv_getattrdsrpc(fhandle_t *fhp, struct ucred *cred,
        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESS);
        NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY);
+       NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SPACEUSED);
        (void) nfsrv_putattrbit(nd, &attrbits);
        error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
            NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
_______________________________________________
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