kernel - Fix slice open mask tracking
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 6 Apr 2011 04:06:03 +0000 (21:06 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 6 Apr 2011 04:06:03 +0000 (21:06 -0700)
* The slice open mask tracking was broken when more than one partition
  on a raw disk device was opened.  Fix the tracking.

* This should solve problems editing the partition information in the
  disklabel for partitions which have been mounted and then unmounted.

* This should also solve problems with the related disk device and
  designation (e.g. da8, da9) being properly disconnected when pulling
  a USB stick.

sys/kern/subr_disk.c
sys/kern/vfs_lock.c
sys/kern/vfs_subr.c

index de816f8..23e4103 100644 (file)
@@ -984,18 +984,25 @@ diskclose(struct dev_close_args *ap)
        cdev_t dev = ap->a_head.a_dev;
        struct disk *dp;
        int error;
+       int lcount;
 
        error = 0;
        dp = dev->si_disk;
 
+       /*
+        * The cdev_t represents the disk/slice/part.  The shared
+        * dp structure governs all cdevs associated with the disk.
+        *
+        * As a safety only close the underlying raw device on the last
+        * close the disk device if our tracking of the slices/partitions
+        * also indicates nothing is open.
+        */
        KKASSERT(dp->d_opencount >= 1);
-       /* If this is not the last close, just ignore it */
-       if ((atomic_fetchadd_int(&dp->d_opencount, -1)) > 1)
-               return 0;
+       lcount = atomic_fetchadd_int(&dp->d_opencount, -1);
 
        get_mplock();
        dsclose(dev, ap->a_devtype, dp->d_slice);
-       if (!dsisopen(dp->d_slice)) {
+       if (lcount <= 1 && !dsisopen(dp->d_slice)) {
                error = dev_dclose(dp->d_rawdev, ap->a_fflag, ap->a_devtype);
        }
        rel_mplock();
index e0829d4..5cf2ca6 100644 (file)
@@ -837,7 +837,7 @@ allocfreevnode(void)
 
 /*
  * Obtain a new vnode from the freelist, allocating more if necessary.
- * The returned vnode is VX locked & refd.
+ * The returned vnode is VX locked & vrefd.
  *
  * All new vnodes set the VAGE flags.  An open() of the vnode will
  * decrement the (2-bit) flags.  Vnodes which are opened several times
index 2b82bc7..ff5f8b4 100644 (file)
@@ -1055,8 +1055,10 @@ reassignbuf(struct buf *bp)
 }
 
 /*
- * Create a vnode for a block device.
- * Used for mounting the root file system.
+ * Create a vnode for a block device.  Used for mounting the root file
+ * system.
+ *
+ * A vref()'d vnode is returned.
  */
 extern struct vop_ops *devfs_vnode_dev_vops_p;
 int