svn commit: r336093 - head/sys/fs/nfsserver

Rick Macklem rmacklem at FreeBSD.org
Sun Jul 8 18:15:56 UTC 2018


Author: rmacklem
Date: Sun Jul  8 18:15:55 2018
New Revision: 336093
URL: https://svnweb.freebsd.org/changeset/base/336093

Log:
  Fix the kernel part of pnfsdscopymr() to handle holes in the file being copied.
  
  If a mirrored DS is being recovered that has a lot of large sparse files,
  pnfsdscopymr(8) would use a lot of space on the recovered mirror since it
  would write the "holes" in the file being mirrored.
  This patch adds code to check for a "hole" and skip doing the write.
  The check is done on a "per PNFSDS_COPYSIZ size block", which is currently 64K.
  I think that most file server file systems will be using a blocksize at
  least this large. If the file server is using a smaller blocksize and
  smaller holes need to be preserved, PNFSDS_COPYSIZ could be decreased.
  The block of 0s is malloc()d, since pnfsdcopymr(8) should be an infrequent
  occurrence.

Modified:
  head/sys/fs/nfsserver/nfs_nfsdkrpc.c
  head/sys/fs/nfsserver/nfs_nfsdstate.c

Modified: head/sys/fs/nfsserver/nfs_nfsdkrpc.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdkrpc.c	Sun Jul  8 16:51:54 2018	(r336092)
+++ head/sys/fs/nfsserver/nfs_nfsdkrpc.c	Sun Jul  8 18:15:55 2018	(r336093)
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
 NFSDLOCKMUTEX;
 NFSV4ROOTLOCKMUTEX;
 struct nfsv4lock nfsd_suspend_lock;
+char *nfsrv_zeropnfsdat = NULL;
 
 /*
  * Mapping of old NFS Version 2 RPC numbers to generic numbers.
@@ -565,6 +566,8 @@ nfsrvd_init(int terminating)
 		nfsrv_freealllayoutsanddevids();
 		nfsrv_freeallbackchannel_xprts();
 		svcpool_close(nfsrvd_pool);
+		free(nfsrv_zeropnfsdat, M_TEMP);
+		nfsrv_zeropnfsdat = NULL;
 		NFSD_LOCK();
 	} else {
 		NFSD_UNLOCK();

Modified: head/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdstate.c	Sun Jul  8 16:51:54 2018	(r336092)
+++ head/sys/fs/nfsserver/nfs_nfsdstate.c	Sun Jul  8 18:15:55 2018	(r336093)
@@ -60,6 +60,7 @@ NFSSTATESPINLOCK;
 extern struct nfsdontlisthead nfsrv_dontlisthead;
 extern volatile int nfsrv_devidcnt;
 extern struct nfslayouthead nfsrv_recalllisthead;
+extern char *nfsrv_zeropnfsdat;
 
 SYSCTL_DECL(_vfs_nfsd);
 int	nfsrv_statehashsize = NFSSTATEHASHSIZE;
@@ -8124,9 +8125,15 @@ tryagain2:
 		if (retacl != 0 && retacl != ENOATTR)
 			NFSD_DEBUG(1, "nfsrv_copymr: vop_getacl=%d\n", retacl);
 		dat = malloc(PNFSDS_COPYSIZ, M_TEMP, M_WAITOK);
+		/* Malloc a block of 0s used to check for holes. */
+		if (nfsrv_zeropnfsdat == NULL)
+			nfsrv_zeropnfsdat = malloc(PNFSDS_COPYSIZ, M_TEMP,
+			    M_WAITOK | M_ZERO);
 		rdpos = wrpos = 0;
 		mp = NULL;
 		ret = vn_start_write(tvp, &mp, V_WAIT | PCATCH);
+		if (ret == 0)
+			ret = VOP_GETATTR(fvp, &va, cred);
 		aresid = 0;
 		while (ret == 0 && aresid == 0) {
 			ret = vn_rdwr(UIO_READ, fvp, dat, PNFSDS_COPYSIZ,
@@ -8135,9 +8142,16 @@ tryagain2:
 			xfer = PNFSDS_COPYSIZ - aresid;
 			if (ret == 0 && xfer > 0) {
 				rdpos += xfer;
-				ret = vn_rdwr(UIO_WRITE, tvp, dat, xfer,
-				    wrpos, UIO_SYSSPACE, IO_NODELOCKED,
-				    cred, NULL, NULL, p);
+				/*
+				 * Skip the write for holes, except for the
+				 * last block.
+				 */
+				if (xfer < PNFSDS_COPYSIZ || rdpos ==
+				    va.va_size || NFSBCMP(dat,
+				    nfsrv_zeropnfsdat, PNFSDS_COPYSIZ) != 0)
+					ret = vn_rdwr(UIO_WRITE, tvp, dat, xfer,
+					    wrpos, UIO_SYSSPACE, IO_NODELOCKED,
+					    cred, NULL, NULL, p);
 				if (ret == 0)
 					wrpos += xfer;
 			}


More information about the svn-src-all mailing list