Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev Make vnd(4) work on sparse files:



details:   https://anonhg.NetBSD.org/src/rev/3abf72307c00
branches:  trunk
changeset: 766670:3abf72307c00
user:      hannken <hannken%NetBSD.org@localhost>
date:      Wed Jun 29 09:12:42 2011 +0000

description:
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@.

diffstat:

 sys/dev/vnd.c    |  32 +++++++++++++++++++++-----------
 sys/dev/vndvar.h |   3 ++-
 2 files changed, 23 insertions(+), 12 deletions(-)

diffs (115 lines):

diff -r 8e699fde4bbd -r 3abf72307c00 sys/dev/vnd.c
--- a/sys/dev/vnd.c     Wed Jun 29 08:37:10 2011 +0000
+++ b/sys/dev/vnd.c     Wed Jun 29 09:12:42 2011 +0000
@@ -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;
diff -r 8e699fde4bbd -r 3abf72307c00 sys/dev/vndvar.h
--- a/sys/dev/vndvar.h  Wed Jun 29 08:37:10 2011 +0000
+++ b/sys/dev/vndvar.h  Wed Jun 29 09:12:42 2011 +0000
@@ -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



Home | Main Index | Thread Index | Old Index