[PATCH] - and RFC - O_EXCL for block devices

From: Neil Brown (neilb@cse.unsw.edu.au)
Date: Wed Jun 12 2002 - 05:05:46 EST


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