Messages in this thread Patch in this message |  | | From | Neil Brown <> | Date | Wed, 12 Jun 2002 20:05:46 +1000 (EST) | Subject | [PATCH] - and RFC - O_EXCL for block devices |
| |
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/
|  |