Module Name: src Committed By: hannken Date: Wed Jun 29 09:12:42 UTC 2011
Modified Files: src/sys/dev: vnd.c vndvar.h Log Message: Make vnd(4) work on sparse files: - Make the strategy decision a device flag and set VNF_USE_VN_RDWR for files known to be sparse. - Change handle_with_rdwr() to use POSIX_FADV_NOREUSE advise to disable read ahead and keep the size of mapped pages below 1 MByte. No objections on tech-kern@. To generate a diff of this commit: cvs rdiff -u -r1.217 -r1.218 src/sys/dev/vnd.c cvs rdiff -u -r1.30 -r1.31 src/sys/dev/vndvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/vnd.c diff -u src/sys/dev/vnd.c:1.217 src/sys/dev/vnd.c:1.218 --- src/sys/dev/vnd.c:1.217 Sun Jun 12 03:35:51 2011 +++ src/sys/dev/vnd.c Wed Jun 29 09:12:42 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: vnd.c,v 1.217 2011/06/12 03:35:51 rmind Exp $ */ +/* $NetBSD: vnd.c,v 1.218 2011/06/29 09:12:42 hannken Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2008 The NetBSD Foundation, Inc. @@ -91,7 +91,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.217 2011/06/12 03:35:51 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.218 2011/06/29 09:12:42 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_vnd.h" @@ -549,7 +549,6 @@ vndthread(void *arg) { struct vnd_softc *vnd = arg; - bool usestrategy; int s; /* Determine whether we can *use* VOP_BMAP and VOP_STRATEGY to @@ -557,12 +556,14 @@ * operations to avoid messing with the local buffer cache. * Otherwise fall back to regular VOP_READ/VOP_WRITE operations * which are guaranteed to work with any file system. */ - usestrategy = vnode_has_strategy(vnd); + if ((vnd->sc_flags & VNF_USE_VN_RDWR) == 0 && + ! vnode_has_strategy(vnd)) + vnd->sc_flags |= VNF_USE_VN_RDWR; #ifdef DEBUG if (vnddebug & VDB_INIT) printf("vndthread: vp %p, %s\n", vnd->sc_vp, - usestrategy ? + (vnd->sc_flags & VNF_USE_VN_RDWR) == 0 ? "using bmap/strategy operations" : "using read/write operations"); #endif @@ -644,7 +645,7 @@ BIO_COPYPRIO(bp, obp); /* Handle the request using the appropriate operations. */ - if (usestrategy) + if ((vnd->sc_flags & VNF_USE_VN_RDWR) == 0) handle_with_strategy(vnd, obp, bp); else handle_with_rdwr(vnd, obp, bp); @@ -696,11 +697,12 @@ { bool doread; off_t offset; - size_t resid; + size_t len, resid; struct vnode *vp; doread = bp->b_flags & B_READ; offset = obp->b_rawblkno * vnd->sc_dkdev.dk_label->d_secsize; + len = bp->b_bcount; vp = vnd->sc_vp; #if defined(DEBUG) @@ -716,10 +718,18 @@ /* Issue the read or write operation. */ bp->b_error = vn_rdwr(doread ? UIO_READ : UIO_WRITE, - vp, bp->b_data, bp->b_bcount, offset, - UIO_SYSSPACE, 0, vnd->sc_cred, &resid, NULL); + vp, bp->b_data, len, offset, UIO_SYSSPACE, + IO_ADV_ENCODE(POSIX_FADV_NOREUSE), vnd->sc_cred, &resid, NULL); bp->b_resid = resid; + /* Keep mapped pages below threshold. */ + mutex_enter(vp->v_interlock); + if (vp->v_uobj.uo_npages > 1024*1024 / PAGE_SIZE) + (void) VOP_PUTPAGES(vp, 0, 0, + PGO_ALLPAGES | PGO_CLEANIT | PGO_FREE | PGO_SYNCIO); + else + mutex_exit(vp->v_interlock); + /* We need to increase the number of outputs on the vnode if * there was any write to it. */ if (!doread) { @@ -1076,8 +1086,8 @@ if (!error && nd.ni_vp->v_type != VREG) error = EOPNOTSUPP; if (!error && vattr.va_bytes < vattr.va_size) - /* File is definitely sparse, reject here */ - error = EINVAL; + /* File is definitely sparse, use vn_rdwr() */ + vnd->sc_flags |= VNF_USE_VN_RDWR; if (error) { VOP_UNLOCK(nd.ni_vp); goto close_and_exit; Index: src/sys/dev/vndvar.h diff -u src/sys/dev/vndvar.h:1.30 src/sys/dev/vndvar.h:1.31 --- src/sys/dev/vndvar.h:1.30 Tue Feb 8 20:20:26 2011 +++ src/sys/dev/vndvar.h Wed Jun 29 09:12:42 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: vndvar.h,v 1.30 2011/02/08 20:20:26 rmind Exp $ */ +/* $NetBSD: vndvar.h,v 1.31 2011/06/29 09:12:42 hannken Exp $ */ /*- * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. @@ -142,6 +142,7 @@ #define VNF_VUNCONF 0x200 /* device is unconfiguring */ #define VNF_COMP 0x400 /* file is compressed */ #define VNF_CLEARING 0x800 /* unit is being torn down */ +#define VNF_USE_VN_RDWR 0x1000 /* have to use vn_rdwr() */ /* structure of header in a compressed file */ struct vnd_comp_header