block: Provide bdev_open_* functions

Create struct bdev_handle that contains all parameters that need to be
passed to blkdev_put() and provide bdev_open_* functions that return
this structure instead of plain bdev pointer. This will eventually allow
us to pass one more argument to blkdev_put() (renamed to bdev_release())
without too much hassle.

Acked-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20230927093442.25915-1-jack@suse.cz
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Jan Kara 2023-09-27 11:34:07 +02:00 committed by Christian Brauner
parent 05d3ef8bba
commit e719b4d156
No known key found for this signature in database
GPG key ID: 91C61BC06578DCA2
2 changed files with 58 additions and 0 deletions

View file

@ -829,6 +829,25 @@ struct block_device *blkdev_get_by_dev(dev_t dev, blk_mode_t mode, void *holder,
}
EXPORT_SYMBOL(blkdev_get_by_dev);
struct bdev_handle *bdev_open_by_dev(dev_t dev, blk_mode_t mode, void *holder,
const struct blk_holder_ops *hops)
{
struct bdev_handle *handle = kmalloc(sizeof(*handle), GFP_KERNEL);
struct block_device *bdev;
if (!handle)
return ERR_PTR(-ENOMEM);
bdev = blkdev_get_by_dev(dev, mode, holder, hops);
if (IS_ERR(bdev)) {
kfree(handle);
return ERR_CAST(bdev);
}
handle->bdev = bdev;
handle->holder = holder;
return handle;
}
EXPORT_SYMBOL(bdev_open_by_dev);
/**
* blkdev_get_by_path - open a block device by name
* @path: path to the block device to open
@ -867,6 +886,28 @@ struct block_device *blkdev_get_by_path(const char *path, blk_mode_t mode,
}
EXPORT_SYMBOL(blkdev_get_by_path);
struct bdev_handle *bdev_open_by_path(const char *path, blk_mode_t mode,
void *holder, const struct blk_holder_ops *hops)
{
struct bdev_handle *handle;
dev_t dev;
int error;
error = lookup_bdev(path, &dev);
if (error)
return ERR_PTR(error);
handle = bdev_open_by_dev(dev, mode, holder, hops);
if (!IS_ERR(handle) && (mode & BLK_OPEN_WRITE) &&
bdev_read_only(handle->bdev)) {
bdev_release(handle);
return ERR_PTR(-EACCES);
}
return handle;
}
EXPORT_SYMBOL(bdev_open_by_path);
void blkdev_put(struct block_device *bdev, void *holder)
{
struct gendisk *disk = bdev->bd_disk;
@ -903,6 +944,13 @@ void blkdev_put(struct block_device *bdev, void *holder)
}
EXPORT_SYMBOL(blkdev_put);
void bdev_release(struct bdev_handle *handle)
{
blkdev_put(handle->bdev, handle->holder);
kfree(handle);
}
EXPORT_SYMBOL(bdev_release);
/**
* lookup_bdev() - Look up a struct block_device by name.
* @pathname: Name of the block device in the filesystem.

View file

@ -1479,14 +1479,24 @@ extern const struct blk_holder_ops fs_holder_ops;
#define sb_open_mode(flags) \
(BLK_OPEN_READ | (((flags) & SB_RDONLY) ? 0 : BLK_OPEN_WRITE))
struct bdev_handle {
struct block_device *bdev;
void *holder;
};
struct block_device *blkdev_get_by_dev(dev_t dev, blk_mode_t mode, void *holder,
const struct blk_holder_ops *hops);
struct block_device *blkdev_get_by_path(const char *path, blk_mode_t mode,
void *holder, const struct blk_holder_ops *hops);
struct bdev_handle *bdev_open_by_dev(dev_t dev, blk_mode_t mode, void *holder,
const struct blk_holder_ops *hops);
struct bdev_handle *bdev_open_by_path(const char *path, blk_mode_t mode,
void *holder, const struct blk_holder_ops *hops);
int bd_prepare_to_claim(struct block_device *bdev, void *holder,
const struct blk_holder_ops *hops);
void bd_abort_claiming(struct block_device *bdev, void *holder);
void blkdev_put(struct block_device *bdev, void *holder);
void bdev_release(struct bdev_handle *handle);
/* just for blk-cgroup, don't use elsewhere */
struct block_device *blkdev_get_no_open(dev_t dev);