fs/block_dev.c contains bd_claim and bd_release that can be used to
provide exclusive access to block devices.
This is currently used when mounting a filesystem from a block device,
when enabling swap to a block device, and when incorporating a block
device into an md/raid array.
This patch
- enhances bd_claim to claim the whole block device when a partition
is claimed and
- (possibly more contravertially) defines open(.., O_EXCL) on a
block device to bd_claim that device for that file. This makes
it trivial for applications like mkfs and fsck to check if a
device is mounted, but does not stop them from accessing the
device that is mounted.
SUS says that open with O_EXCL but without O_CREAT is undefined,
so this doesn't break SUS compliance.
Other places where bd_claim should be used:
LVM
loop
but I'll leave those for others to fix.
NeilBrown
(patch against 2.5.21 ... actually cset 1.474)
### Comments for ChangeSet
Extension to block device claiming
1/ when a partition is claimed, claim the whole device for partitioning
2/ when a blockdev is opened O_EXCL, claim for that file.
----------- Diffstat output ------------
block_dev.c | 38 ++++++++++++++++++++++++++++++++++----
1 files changed, 34 insertions(+), 4 deletions(-)
--- ./fs/block_dev.c 2002/06/12 06:20:49 1.1
+++ ./fs/block_dev.c 2002/06/12 09:57:41
@@ -376,15 +376,34 @@
spin_unlock(&bdev_lock);
}
-int bd_claim(struct block_device *bdev, void *holder)
+static int __bd_claim(struct block_device *bdev, void *holder)
{
int res = -EBUSY;
- spin_lock(&bdev_lock);
if (!bdev->bd_holder || bdev->bd_holder == holder) {
bdev->bd_holder = holder;
bdev->bd_holders++;
res = 0;
}
+ return res;
+}
+
+static void __bd_release(struct block_device *bdev)
+{
+ if (!--bdev->bd_holders)
+ bdev->bd_holder = NULL;
+}
+
+int bd_claim(struct block_device *bdev, void *holder)
+{
+ int res = 0;
+ spin_lock(&bdev_lock);
+ if (bdev->bd_contains != bdev)
+ res = __bd_claim(bdev->bd_contains, bd_claim);
+ if (!res) {
+ res = __bd_claim(bdev, holder);
+ if (res && bdev->bd_contains != bdev)
+ __bd_release(bdev->bd_contains);
+ }
spin_unlock(&bdev_lock);
return res;
}
@@ -392,8 +411,9 @@
void bd_release(struct block_device *bdev)
{
spin_lock(&bdev_lock);
- if (!--bdev->bd_holders)
- bdev->bd_holder = NULL;
+ if (bdev->bd_contains != bdev)
+ __bd_release(bdev->bd_contains);
+ __bd_release(bdev);
spin_unlock(&bdev_lock);
}
@@ -653,6 +673,14 @@
bd_acquire(inode);
bdev = inode->i_bdev;
+ if (filp->f_flags & O_EXCL) {
+ int res = bd_claim(bdev, filp);
+ if (res) {
+ bdput(bdev);
+ return res;
+ }
+ }
+
return do_open(bdev, inode, filp);
}
@@ -692,6 +720,8 @@
int blkdev_close(struct inode * inode, struct file * filp)
{
+ if (inode->i_bdev->bd_holder == filp)
+ bd_release(inode->i_bdev);
return blkdev_put(inode->i_bdev, BDEV_FILE);
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sat Jun 15 2002 - 22:00:25 EST