block: Provide bdev_open_* functions
[ Upstream commit e719b4d156749f02eafed31a3c515f2aa9dcc72a ] 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> Stable-dep-of: 0f28be64d132 ("erofs: fix lockdep false positives on initializing erofs_pseudo_mnt") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
3721c63d30
commit
dd0bd42912
48
block/bdev.c
48
block/bdev.c
|
@ -831,6 +831,25 @@ put_blkdev:
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(blkdev_get_by_dev);
|
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
|
* blkdev_get_by_path - open a block device by name
|
||||||
* @path: path to the block device to open
|
* @path: path to the block device to open
|
||||||
|
@ -869,6 +888,28 @@ struct block_device *blkdev_get_by_path(const char *path, blk_mode_t mode,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(blkdev_get_by_path);
|
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)
|
void blkdev_put(struct block_device *bdev, void *holder)
|
||||||
{
|
{
|
||||||
struct gendisk *disk = bdev->bd_disk;
|
struct gendisk *disk = bdev->bd_disk;
|
||||||
|
@ -905,6 +946,13 @@ void blkdev_put(struct block_device *bdev, void *holder)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(blkdev_put);
|
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.
|
* lookup_bdev() - Look up a struct block_device by name.
|
||||||
* @pathname: Name of the block device in the filesystem.
|
* @pathname: Name of the block device in the filesystem.
|
||||||
|
|
|
@ -1479,14 +1479,24 @@ extern const struct blk_holder_ops fs_holder_ops;
|
||||||
#define sb_open_mode(flags) \
|
#define sb_open_mode(flags) \
|
||||||
(BLK_OPEN_READ | (((flags) & SB_RDONLY) ? 0 : BLK_OPEN_WRITE))
|
(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,
|
struct block_device *blkdev_get_by_dev(dev_t dev, blk_mode_t mode, void *holder,
|
||||||
const struct blk_holder_ops *hops);
|
const struct blk_holder_ops *hops);
|
||||||
struct block_device *blkdev_get_by_path(const char *path, blk_mode_t mode,
|
struct block_device *blkdev_get_by_path(const char *path, blk_mode_t mode,
|
||||||
void *holder, const struct blk_holder_ops *hops);
|
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,
|
int bd_prepare_to_claim(struct block_device *bdev, void *holder,
|
||||||
const struct blk_holder_ops *hops);
|
const struct blk_holder_ops *hops);
|
||||||
void bd_abort_claiming(struct block_device *bdev, void *holder);
|
void bd_abort_claiming(struct block_device *bdev, void *holder);
|
||||||
void blkdev_put(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 */
|
/* just for blk-cgroup, don't use elsewhere */
|
||||||
struct block_device *blkdev_get_no_open(dev_t dev);
|
struct block_device *blkdev_get_no_open(dev_t dev);
|
||||||
|
|
Loading…
Reference in New Issue