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.
This commit is contained in:
parent
f3d2853f4b
commit
da485b59a5
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user