HAMMER VFS - Fix umount panic related to volume flush
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 15 Jan 2010 23:20:41 +0000 (15:20 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 15 Jan 2010 23:20:41 +0000 (15:20 -0800)
* A volume undergoing I/O as-of the time of a umount can recurse within
  hammer_io_release() due to improper ref-count handling.

* Properly reference and flus hthe volume during umount instead of
  trying to call hammer_io_release() directly.

Reported-by: Jan Lentfer <Jan.Lentfer@web.de>
sys/vfs/hammer/hammer_ondisk.c

index 2a6a2c2..83c61a2 100644 (file)
@@ -270,7 +270,6 @@ hammer_unload_volume(hammer_volume_t volume, void *data __unused)
 {
        hammer_mount_t hmp = volume->io.hmp;
        int ronly = ((hmp->mp->mnt_flag & MNT_RDONLY) ? 1 : 0);
-       struct buf *bp;
 
        /*
         * Clean up the root volume pointer, which is held unlocked in hmp.
@@ -285,7 +284,6 @@ hammer_unload_volume(hammer_volume_t volume, void *data __unused)
         */
        hammer_io_clear_modify(&volume->io, 1);
        volume->io.waitdep = 1;
-       bp = hammer_io_release(&volume->io, 1);
 
        /*
         * Clean up the persistent ref ioerror might have on the volume
@@ -296,12 +294,18 @@ hammer_unload_volume(hammer_volume_t volume, void *data __unused)
        }
 
        /*
+        * This should release the bp.
+        */
+       KKASSERT(volume->io.lock.refs == 0);
+       hammer_ref(&volume->io.lock);
+       hammer_rel_volume(volume, 1);
+       KKASSERT(volume->io.bp == NULL);
+
+       /*
         * There should be no references on the volume, no clusters, and
         * no super-clusters.
         */
        KKASSERT(volume->io.lock.refs == 0);
-       if (bp)
-               brelse(bp);
 
        volume->ondisk = NULL;
        if (volume->devvp) {