HAMMER 46B/Many: Stabilization pass
authorMatthew Dillon <dillon@dragonflybsd.org>
Sun, 18 May 2008 21:47:06 +0000 (21:47 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Sun, 18 May 2008 21:47:06 +0000 (21:47 +0000)
* Add a feature to vmntvnodescan() to only do one pass on the vnode list.
  Have HAMMER use it.

* Fix a buffer cache leak.  Buffers could wind up disassociated from their
  HAMMER structures while in a B_LOCKED state, preventing the kernel from
  reusing them.

sys/kern/vfs_mount.c
sys/sys/vnode.h
sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_io.c
sys/vfs/hammer/hammer_ondisk.c

index 4237687..a1d08ad 100644 (file)
@@ -67,7 +67,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/vfs_mount.c,v 1.33 2008/05/18 05:54:25 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_mount.c,v 1.34 2008/05/18 21:47:02 dillon Exp $
  */
 
 /*
@@ -911,10 +911,19 @@ vmntvnodescan(
        struct vnode *vp;
        int r = 0;
        int maxcount = 1000000;
+       int stopcount = 0;
        int count = 0;
 
        lwkt_gettoken(&ilock, &mntvnode_token);
 
+       /*
+        * If asked to do one pass stop after iterating available vnodes.
+        * Under heavy loads new vnodes can be added while we are scanning,
+        * so this isn't perfect.  Create a slop factor of 2x.
+        */
+       if (flags & VMSC_ONEPASS)
+               stopcount = mp->mnt_nvnodelistsize * 2;
+
        info.vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
        TAILQ_INSERT_TAIL(&mntvnodescan_list, &info, entry);
        while ((vp = info.vp) != NULL) {
@@ -948,7 +957,7 @@ vmntvnodescan(
                if (slowfunc) {
                        int error;
 
-                       switch(flags) {
+                       switch(flags & (VMSC_GETVP|VMSC_GETVX|VMSC_NOWAIT)) {
                        case VMSC_GETVP:
                                error = vget(vp, LK_EXCLUSIVE);
                                break;
@@ -976,7 +985,7 @@ vmntvnodescan(
                        /*
                         * Cleanup
                         */
-                       switch(flags) {
+                       switch(flags & (VMSC_GETVP|VMSC_GETVX|VMSC_NOWAIT)) {
                        case VMSC_GETVP:
                        case VMSC_GETVP|VMSC_NOWAIT:
                                vput(vp);
@@ -1005,6 +1014,14 @@ next:
                        count = 0;
                }
 
+               /*
+                * If doing one pass this decrements to zero.  If it starts
+                * at zero it is effectively unlimited for the purposes of
+                * this loop.
+                */
+               if (--stopcount == 0)
+                       break;
+
                /*
                 * Iterate.  If the vnode was ripped out from under us
                 * info.vp will already point to the next vnode, otherwise
index 474044b..2de4241 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)vnode.h     8.7 (Berkeley) 2/4/94
  * $FreeBSD: src/sys/sys/vnode.h,v 1.111.2.19 2002/12/29 18:19:53 dillon Exp $
- * $DragonFly: src/sys/sys/vnode.h,v 1.79 2008/05/18 05:54:30 dillon Exp $
+ * $DragonFly: src/sys/sys/vnode.h,v 1.80 2008/05/18 21:47:05 dillon Exp $
  */
 
 #ifndef _SYS_VNODE_H_
@@ -287,9 +287,10 @@ struct vnode {
 /*
  * vmntvnodescan() flags
  */
-#define VMSC_GETVP     1
-#define VMSC_GETVX     2
+#define VMSC_GETVP     0x01
+#define VMSC_GETVX     0x02
 #define VMSC_NOWAIT    0x10
+#define VMSC_ONEPASS   0x20
 
 /*
  * Flags for ioflag. (high 16 bits used to ask for read-ahead and
index dcdb28c..5b1ede7 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.69 2008/05/18 01:48:50 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.70 2008/05/18 21:47:06 dillon Exp $
  */
 /*
  * This header file contains structures used internally by the HAMMERFS
@@ -843,7 +843,6 @@ int hammer_io_read(struct vnode *devvp, struct hammer_io *io,
 int hammer_io_new(struct vnode *devvp, struct hammer_io *io);
 void hammer_io_release(struct hammer_io *io, int flush);
 void hammer_io_flush(struct hammer_io *io);
-int hammer_io_checkflush(hammer_io_t io);
 void hammer_io_clear_modify(struct hammer_io *io);
 void hammer_io_waitdep(struct hammer_io *io);
 
index 24a201e..8058698 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_io.c,v 1.32 2008/05/18 01:48:50 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_io.c,v 1.33 2008/05/18 21:47:06 dillon Exp $
  */
 /*
  * IO Primitives and buffer cache management
@@ -332,8 +332,23 @@ hammer_io_release(struct hammer_io *io, int flush)
                 * structure and use bioops to disconnect it later on
                 * if the kernel wants to discard the buffer.
                 */
+               bp->b_flags &= ~B_LOCKED;
                io->released = 1;
                bqrelse(bp);
+       } else {
+               /*
+                * A released buffer may have been locked when the kernel
+                * tried to deallocate it while HAMMER still had references
+                * on the hammer_buffer.  We must unlock the buffer or
+                * it will just rot.
+                */
+               crit_enter();
+               if (io->running == 0 && (bp->b_flags & B_LOCKED)) {
+                       regetblk(bp);
+                       bp->b_flags &= ~B_LOCKED;
+                       bqrelse(bp);
+               }
+               crit_exit();
        }
 }
 
@@ -747,19 +762,6 @@ hammer_io_checkwrite(struct buf *bp)
        return(0);
 }
 
-/*
- * Return non-zero if the caller should flush the structure associated
- * with this io sub-structure.
- */
-int
-hammer_io_checkflush(struct hammer_io *io)
-{
-       if (io->bp == NULL || (io->bp->b_flags & B_LOCKED)) {
-               return(1);
-       }
-       return(0);
-}
-
 /*
  * Return non-zero if we wish to delay the kernel's attempt to flush
  * this buffer to disk.
index 5865213..bb33eab 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_ondisk.c,v 1.46 2008/05/18 01:48:50 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_ondisk.c,v 1.47 2008/05/18 21:47:06 dillon Exp $
  */
 /*
  * Manage HAMMER's on-disk structures.  These routines are primarily
@@ -1402,10 +1402,10 @@ hammer_queue_inodes_flusher(hammer_mount_t hmp, int waitfor)
        info.error = 0;
        info.waitfor = waitfor;
        if (waitfor == MNT_WAIT) {
-               vmntvnodescan(hmp->mp, VMSC_GETVP,
+               vmntvnodescan(hmp->mp, VMSC_GETVP|VMSC_ONEPASS,
                              hammer_sync_scan1, hammer_sync_scan2, &info);
        } else {
-               vmntvnodescan(hmp->mp, VMSC_GETVP|VMSC_NOWAIT,
+               vmntvnodescan(hmp->mp, VMSC_GETVP|VMSC_ONEPASS|VMSC_NOWAIT,
                              hammer_sync_scan1, hammer_sync_scan2, &info);
        }
        return(info.error);