* Change the offset alignment in vn_rdwe_inchunks()
authorDavid Rhodus <drhodus@dragonflybsd.org>
Mon, 29 Mar 2004 15:21:42 +0000 (15:21 +0000)
committerDavid Rhodus <drhodus@dragonflybsd.org>
Mon, 29 Mar 2004 15:21:42 +0000 (15:21 +0000)
This is primarily used by the ELF image activator.

FreeBSD src repository

  Modified files:
    sys/kern             vfs_vnops.c
  Log:
  Align the offset in vn_rdwr_inchunks() so that at most the first and
  the last chunk are misaligned relative to a MAXBSIZE byte boundary.
  vn_rdwr_inchunks() is used mainly for elf core dumps, and elf sections
  are usually perfectly misaligned relative to MAXBSIZE, and chunking
  prevents the file system from doing much realigning.

  This gives a surprisingly large speedup for core dumps -- from 50 to
  13 seconds for a 512MB core dump here.  The pessimization was mostly
  from an interaction of the misalignment with IO_DIRECT.  It increased
  the number of i/o's for each chunk by a factor of 5 (3 writes and 2
  read-before-writes instead of 1 write).

sys/kern/vfs_vnops.c

index 1cd02eb..92a448e 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94
  * $FreeBSD: src/sys/kern/vfs_vnops.c,v 1.87.2.13 2002/12/29 18:19:53 dillon Exp $
- * $DragonFly: src/sys/kern/vfs_vnops.c,v 1.16 2004/03/01 06:33:17 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_vnops.c,v 1.17 2004/03/29 15:21:42 drhodus Exp $
  */
 
 #include <sys/param.h>
@@ -340,8 +340,18 @@ vn_rdwr_inchunks(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, td)
        int error = 0;
 
        do {
-               int chunk = (len > MAXBSIZE) ? MAXBSIZE : len;
+               int chunk;
 
+               /*
+                * Force `offset' to a multiple of MAXBSIZE except possibly
+                * for the first chunk, so that filesystems only need to
+                * write full blocks except possibly for the first and last
+                * chunks.
+                */
+               chunk = MAXBSIZE - (uoff_t)offset % MAXBSIZE;
+
+               if (chunk > len)
+                       chunk = len;
                if (rw != UIO_READ && vp->v_type == VREG)
                        bwillwrite();
                error = vn_rdwr(rw, vp, base, chunk, offset, segflg,
@@ -658,7 +668,7 @@ debug_vn_lock(struct vnode *vp, lwkt_tokref_t vlock, int flags,
                        error = VOP_LOCK(vp, vlock,
                                    flags | LK_NOPAUSE | LK_INTERLOCK, td);
                        if (error == 0)
-                               return (error);
+                               return (0);
                }
                flags &= ~LK_INTERLOCK;
        } while (flags & LK_RETRY);