From 2d5beb816b67efa1ff2c95587b78b442b1f1b249 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 5 Apr 2011 21:06:03 -0700 Subject: [PATCH] kernel - Fix slice open mask tracking * 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 | 15 +++++++++++---- sys/kern/vfs_lock.c | 2 +- sys/kern/vfs_subr.c | 6 ++++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c index de816f8..23e4103 100644 --- a/sys/kern/subr_disk.c +++ b/sys/kern/subr_disk.c @@ -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(); diff --git a/sys/kern/vfs_lock.c b/sys/kern/vfs_lock.c index e0829d4..5cf2ca6 100644 --- a/sys/kern/vfs_lock.c +++ b/sys/kern/vfs_lock.c @@ -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 diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 2b82bc7..ff5f8b4 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -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 -- 1.7.7.2