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