mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
block: introduce holder ops
Add a new blk_holder_ops structure, which is passed to blkdev_get_by_* and installed in the block_device for exclusive claims. It will be used to allow the block layer to call back into the user of the block device for thing like notification of a removed device or a device resize. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Jan Kara <jack@suse.cz> Acked-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Link: https://lore.kernel.org/r/20230601094459.1350643-10-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
committed by
Jens Axboe
parent
00080f7fb7
commit
0718afd47f
41
block/bdev.c
41
block/bdev.c
@@ -102,7 +102,7 @@ int truncate_bdev_range(struct block_device *bdev, fmode_t mode,
|
||||
* under live filesystem.
|
||||
*/
|
||||
if (!(mode & FMODE_EXCL)) {
|
||||
int err = bd_prepare_to_claim(bdev, truncate_bdev_range);
|
||||
int err = bd_prepare_to_claim(bdev, truncate_bdev_range, NULL);
|
||||
if (err)
|
||||
goto invalidate;
|
||||
}
|
||||
@@ -415,6 +415,7 @@ struct block_device *bdev_alloc(struct gendisk *disk, u8 partno)
|
||||
bdev = I_BDEV(inode);
|
||||
mutex_init(&bdev->bd_fsfreeze_mutex);
|
||||
spin_lock_init(&bdev->bd_size_lock);
|
||||
mutex_init(&bdev->bd_holder_lock);
|
||||
bdev->bd_partno = partno;
|
||||
bdev->bd_inode = inode;
|
||||
bdev->bd_queue = disk->queue;
|
||||
@@ -464,13 +465,15 @@ long nr_blockdev_pages(void)
|
||||
* bd_may_claim - test whether a block device can be claimed
|
||||
* @bdev: block device of interest
|
||||
* @holder: holder trying to claim @bdev
|
||||
* @hops: holder ops
|
||||
*
|
||||
* Test whether @bdev can be claimed by @holder.
|
||||
*
|
||||
* RETURNS:
|
||||
* %true if @bdev can be claimed, %false otherwise.
|
||||
*/
|
||||
static bool bd_may_claim(struct block_device *bdev, void *holder)
|
||||
static bool bd_may_claim(struct block_device *bdev, void *holder,
|
||||
const struct blk_holder_ops *hops)
|
||||
{
|
||||
struct block_device *whole = bdev_whole(bdev);
|
||||
|
||||
@@ -480,8 +483,11 @@ static bool bd_may_claim(struct block_device *bdev, void *holder)
|
||||
/*
|
||||
* The same holder can always re-claim.
|
||||
*/
|
||||
if (bdev->bd_holder == holder)
|
||||
if (bdev->bd_holder == holder) {
|
||||
if (WARN_ON_ONCE(bdev->bd_holder_ops != hops))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -499,6 +505,7 @@ static bool bd_may_claim(struct block_device *bdev, void *holder)
|
||||
* bd_prepare_to_claim - claim a block device
|
||||
* @bdev: block device of interest
|
||||
* @holder: holder trying to claim @bdev
|
||||
* @hops: holder ops.
|
||||
*
|
||||
* Claim @bdev. This function fails if @bdev is already claimed by another
|
||||
* holder and waits if another claiming is in progress. return, the caller
|
||||
@@ -507,7 +514,8 @@ static bool bd_may_claim(struct block_device *bdev, void *holder)
|
||||
* RETURNS:
|
||||
* 0 if @bdev can be claimed, -EBUSY otherwise.
|
||||
*/
|
||||
int bd_prepare_to_claim(struct block_device *bdev, void *holder)
|
||||
int bd_prepare_to_claim(struct block_device *bdev, void *holder,
|
||||
const struct blk_holder_ops *hops)
|
||||
{
|
||||
struct block_device *whole = bdev_whole(bdev);
|
||||
|
||||
@@ -516,7 +524,7 @@ int bd_prepare_to_claim(struct block_device *bdev, void *holder)
|
||||
retry:
|
||||
mutex_lock(&bdev_lock);
|
||||
/* if someone else claimed, fail */
|
||||
if (!bd_may_claim(bdev, holder)) {
|
||||
if (!bd_may_claim(bdev, holder, hops)) {
|
||||
mutex_unlock(&bdev_lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -557,12 +565,13 @@ static void bd_clear_claiming(struct block_device *whole, void *holder)
|
||||
* Finish exclusive open of a block device. Mark the device as exlusively
|
||||
* open by the holder and wake up all waiters for exclusive open to finish.
|
||||
*/
|
||||
static void bd_finish_claiming(struct block_device *bdev, void *holder)
|
||||
static void bd_finish_claiming(struct block_device *bdev, void *holder,
|
||||
const struct blk_holder_ops *hops)
|
||||
{
|
||||
struct block_device *whole = bdev_whole(bdev);
|
||||
|
||||
mutex_lock(&bdev_lock);
|
||||
BUG_ON(!bd_may_claim(bdev, holder));
|
||||
BUG_ON(!bd_may_claim(bdev, holder, hops));
|
||||
/*
|
||||
* Note that for a whole device bd_holders will be incremented twice,
|
||||
* and bd_holder will be set to bd_may_claim before being set to holder
|
||||
@@ -570,7 +579,10 @@ static void bd_finish_claiming(struct block_device *bdev, void *holder)
|
||||
whole->bd_holders++;
|
||||
whole->bd_holder = bd_may_claim;
|
||||
bdev->bd_holders++;
|
||||
mutex_lock(&bdev->bd_holder_lock);
|
||||
bdev->bd_holder = holder;
|
||||
bdev->bd_holder_ops = hops;
|
||||
mutex_unlock(&bdev->bd_holder_lock);
|
||||
bd_clear_claiming(whole, holder);
|
||||
mutex_unlock(&bdev_lock);
|
||||
}
|
||||
@@ -605,7 +617,10 @@ static void bd_end_claim(struct block_device *bdev)
|
||||
WARN_ON_ONCE(--bdev->bd_holders < 0);
|
||||
WARN_ON_ONCE(--whole->bd_holders < 0);
|
||||
if (!bdev->bd_holders) {
|
||||
mutex_lock(&bdev->bd_holder_lock);
|
||||
bdev->bd_holder = NULL;
|
||||
bdev->bd_holder_ops = NULL;
|
||||
mutex_unlock(&bdev->bd_holder_lock);
|
||||
if (bdev->bd_write_holder)
|
||||
unblock = true;
|
||||
}
|
||||
@@ -735,6 +750,7 @@ void blkdev_put_no_open(struct block_device *bdev)
|
||||
* @dev: device number of block device to open
|
||||
* @mode: FMODE_* mask
|
||||
* @holder: exclusive holder identifier
|
||||
* @hops: holder operations
|
||||
*
|
||||
* Open the block device described by device number @dev. If @mode includes
|
||||
* %FMODE_EXCL, the block device is opened with exclusive access. Specifying
|
||||
@@ -751,7 +767,8 @@ void blkdev_put_no_open(struct block_device *bdev)
|
||||
* RETURNS:
|
||||
* Reference to the block_device on success, ERR_PTR(-errno) on failure.
|
||||
*/
|
||||
struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
|
||||
struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder,
|
||||
const struct blk_holder_ops *hops)
|
||||
{
|
||||
bool unblock_events = true;
|
||||
struct block_device *bdev;
|
||||
@@ -771,7 +788,7 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
|
||||
disk = bdev->bd_disk;
|
||||
|
||||
if (mode & FMODE_EXCL) {
|
||||
ret = bd_prepare_to_claim(bdev, holder);
|
||||
ret = bd_prepare_to_claim(bdev, holder, hops);
|
||||
if (ret)
|
||||
goto put_blkdev;
|
||||
}
|
||||
@@ -791,7 +808,7 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
|
||||
if (ret)
|
||||
goto put_module;
|
||||
if (mode & FMODE_EXCL) {
|
||||
bd_finish_claiming(bdev, holder);
|
||||
bd_finish_claiming(bdev, holder, hops);
|
||||
|
||||
/*
|
||||
* Block event polling for write claims if requested. Any write
|
||||
@@ -842,7 +859,7 @@ EXPORT_SYMBOL(blkdev_get_by_dev);
|
||||
* Reference to the block_device on success, ERR_PTR(-errno) on failure.
|
||||
*/
|
||||
struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
|
||||
void *holder)
|
||||
void *holder, const struct blk_holder_ops *hops)
|
||||
{
|
||||
struct block_device *bdev;
|
||||
dev_t dev;
|
||||
@@ -852,7 +869,7 @@ struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
|
||||
if (error)
|
||||
return ERR_PTR(error);
|
||||
|
||||
bdev = blkdev_get_by_dev(dev, mode, holder);
|
||||
bdev = blkdev_get_by_dev(dev, mode, holder, hops);
|
||||
if (!IS_ERR(bdev) && (mode & FMODE_WRITE) && bdev_read_only(bdev)) {
|
||||
blkdev_put(bdev, mode);
|
||||
return ERR_PTR(-EACCES);
|
||||
|
Reference in New Issue
Block a user