svn commit: r354989 - in head/sys/fs: nfs nfsserver

Rick Macklem rmacklem at FreeBSD.org
Fri Nov 22 00:22:56 UTC 2019


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);


More information about the svn-src-head mailing list