Skip to content

Commit a56aefc

Browse files
committed
bdev: make struct bdev_handle private to the block layer
Link: https://lore.kernel.org/r/20240123-vfs-bdev-file-v2-29-adbd023e19cc@kernel.org Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent b1211a2 commit a56aefc

File tree

5 files changed

+86
-95
lines changed

5 files changed

+86
-95
lines changed

block/bdev.c

Lines changed: 61 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,24 @@ static int blkdev_get_part(struct block_device *part, blk_mode_t mode)
703703
return ret;
704704
}
705705

706+
int bdev_permission(dev_t dev, blk_mode_t mode, void *holder)
707+
{
708+
int ret;
709+
710+
ret = devcgroup_check_permission(DEVCG_DEV_BLOCK,
711+
MAJOR(dev), MINOR(dev),
712+
((mode & BLK_OPEN_READ) ? DEVCG_ACC_READ : 0) |
713+
((mode & BLK_OPEN_WRITE) ? DEVCG_ACC_WRITE : 0));
714+
if (ret)
715+
return ret;
716+
717+
/* Blocking writes requires exclusive opener */
718+
if (mode & BLK_OPEN_RESTRICT_WRITES && !holder)
719+
return -EINVAL;
720+
721+
return 0;
722+
}
723+
706724
static void blkdev_put_part(struct block_device *part)
707725
{
708726
struct block_device *whole = bdev_whole(part);
@@ -795,69 +813,43 @@ static void bdev_yield_write_access(struct block_device *bdev, blk_mode_t mode)
795813
}
796814

797815
/**
798-
* bdev_open_by_dev - open a block device by device number
799-
* @dev: device number of block device to open
816+
* bdev_open - open a block device
817+
* @bdev: block device to open
800818
* @mode: open mode (BLK_OPEN_*)
801819
* @holder: exclusive holder identifier
802820
* @hops: holder operations
821+
* @bdev_file: file for the block device
803822
*
804-
* Open the block device described by device number @dev. If @holder is not
805-
* %NULL, the block device is opened with exclusive access. Exclusive opens may
806-
* nest for the same @holder.
807-
*
808-
* Use this interface ONLY if you really do not have anything better - i.e. when
809-
* you are behind a truly sucky interface and all you are given is a device
810-
* number. Everything else should use bdev_open_by_path().
823+
* Open the block device. If @holder is not %NULL, the block device is opened
824+
* with exclusive access. Exclusive opens may nest for the same @holder.
811825
*
812826
* CONTEXT:
813827
* Might sleep.
814828
*
815829
* RETURNS:
816-
* Handle with a reference to the block_device on success, ERR_PTR(-errno) on
817-
* failure.
830+
* zero on success, -errno on failure.
818831
*/
819-
struct bdev_handle *bdev_open_by_dev(dev_t dev, blk_mode_t mode, void *holder,
820-
const struct blk_holder_ops *hops)
832+
int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
833+
const struct blk_holder_ops *hops, struct file *bdev_file)
821834
{
822-
struct bdev_handle *handle = kmalloc(sizeof(struct bdev_handle),
823-
GFP_KERNEL);
824-
struct block_device *bdev;
835+
struct bdev_handle *handle;
825836
bool unblock_events = true;
826-
struct gendisk *disk;
837+
struct gendisk *disk = bdev->bd_disk;
827838
int ret;
828839

840+
handle = kmalloc(sizeof(struct bdev_handle), GFP_KERNEL);
829841
if (!handle)
830-
return ERR_PTR(-ENOMEM);
831-
832-
ret = devcgroup_check_permission(DEVCG_DEV_BLOCK,
833-
MAJOR(dev), MINOR(dev),
834-
((mode & BLK_OPEN_READ) ? DEVCG_ACC_READ : 0) |
835-
((mode & BLK_OPEN_WRITE) ? DEVCG_ACC_WRITE : 0));
836-
if (ret)
837-
goto free_handle;
838-
839-
/* Blocking writes requires exclusive opener */
840-
if (mode & BLK_OPEN_RESTRICT_WRITES && !holder) {
841-
ret = -EINVAL;
842-
goto free_handle;
843-
}
844-
845-
bdev = blkdev_get_no_open(dev);
846-
if (!bdev) {
847-
ret = -ENXIO;
848-
goto free_handle;
849-
}
850-
disk = bdev->bd_disk;
842+
return -ENOMEM;
851843

852844
if (holder) {
853845
mode |= BLK_OPEN_EXCL;
854846
ret = bd_prepare_to_claim(bdev, holder, hops);
855847
if (ret)
856-
goto put_blkdev;
848+
goto free_handle;
857849
} else {
858850
if (WARN_ON_ONCE(mode & BLK_OPEN_EXCL)) {
859851
ret = -EIO;
860-
goto put_blkdev;
852+
goto free_handle;
861853
}
862854
}
863855

@@ -902,19 +894,26 @@ struct bdev_handle *bdev_open_by_dev(dev_t dev, blk_mode_t mode, void *holder,
902894
handle->bdev = bdev;
903895
handle->holder = holder;
904896
handle->mode = mode;
905-
return handle;
897+
898+
bdev_file->f_flags |= O_LARGEFILE;
899+
bdev_file->f_mode |= FMODE_BUF_RASYNC | FMODE_CAN_ODIRECT;
900+
if (bdev_nowait(bdev))
901+
bdev_file->f_mode |= FMODE_NOWAIT;
902+
bdev_file->f_mapping = handle->bdev->bd_inode->i_mapping;
903+
bdev_file->f_wb_err = filemap_sample_wb_err(bdev_file->f_mapping);
904+
bdev_file->private_data = handle;
905+
906+
return 0;
906907
put_module:
907908
module_put(disk->fops->owner);
908909
abort_claiming:
909910
if (holder)
910911
bd_abort_claiming(bdev, holder);
911912
mutex_unlock(&disk->open_mutex);
912913
disk_unblock_events(disk);
913-
put_blkdev:
914-
blkdev_put_no_open(bdev);
915914
free_handle:
916915
kfree(handle);
917-
return ERR_PTR(ret);
916+
return ret;
918917
}
919918

920919
/*
@@ -951,29 +950,33 @@ struct file *bdev_file_open_by_dev(dev_t dev, blk_mode_t mode, void *holder,
951950
const struct blk_holder_ops *hops)
952951
{
953952
struct file *bdev_file;
954-
struct bdev_handle *handle;
953+
struct block_device *bdev;
955954
unsigned int flags;
955+
int ret;
956956

957-
handle = bdev_open_by_dev(dev, mode, holder, hops);
958-
if (IS_ERR(handle))
959-
return ERR_CAST(handle);
957+
ret = bdev_permission(dev, mode, holder);
958+
if (ret)
959+
return ERR_PTR(ret);
960+
961+
bdev = blkdev_get_no_open(dev);
962+
if (!bdev)
963+
return ERR_PTR(-ENXIO);
960964

961965
flags = blk_to_file_flags(mode);
962-
bdev_file = alloc_file_pseudo_noaccount(handle->bdev->bd_inode,
966+
bdev_file = alloc_file_pseudo_noaccount(bdev->bd_inode,
963967
blockdev_mnt, "", flags | O_LARGEFILE, &def_blk_fops);
964968
if (IS_ERR(bdev_file)) {
965-
bdev_release(handle);
969+
blkdev_put_no_open(bdev);
966970
return bdev_file;
967971
}
968-
ihold(handle->bdev->bd_inode);
972+
ihold(bdev->bd_inode);
969973

970-
bdev_file->f_mode |= FMODE_BUF_RASYNC | FMODE_CAN_ODIRECT;
971-
if (bdev_nowait(handle->bdev))
972-
bdev_file->f_mode |= FMODE_NOWAIT;
973-
974-
bdev_file->f_mapping = handle->bdev->bd_inode->i_mapping;
975-
bdev_file->f_wb_err = filemap_sample_wb_err(bdev_file->f_mapping);
976-
bdev_file->private_data = handle;
974+
ret = bdev_open(bdev, mode, holder, hops, bdev_file);
975+
if (ret) {
976+
blkdev_put_no_open(bdev);
977+
fput(bdev_file);
978+
return ERR_PTR(ret);
979+
}
977980
return bdev_file;
978981
}
979982
EXPORT_SYMBOL(bdev_file_open_by_dev);

block/blk.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ struct blk_flush_queue {
2525
struct request *flush_rq;
2626
};
2727

28+
struct bdev_handle {
29+
struct block_device *bdev;
30+
void *holder;
31+
blk_mode_t mode;
32+
};
33+
2834
bool is_flush_rq(struct request *req);
2935

3036
struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
@@ -517,7 +523,7 @@ static inline int req_ref_read(struct request *req)
517523
}
518524

519525
void bdev_release(struct bdev_handle *handle);
520-
struct bdev_handle *bdev_open_by_dev(dev_t dev, blk_mode_t mode, void *holder,
521-
const struct blk_holder_ops *hops);
522-
526+
int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
527+
const struct blk_holder_ops *hops, struct file *bdev_file);
528+
int bdev_permission(dev_t dev, blk_mode_t mode, void *holder);
523529
#endif /* BLK_INTERNAL_H */

block/fops.c

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -599,36 +599,31 @@ blk_mode_t file_to_blk_mode(struct file *file)
599599

600600
static int blkdev_open(struct inode *inode, struct file *filp)
601601
{
602-
struct bdev_handle *handle;
602+
struct block_device *bdev;
603603
blk_mode_t mode;
604-
605-
/*
606-
* Preserve backwards compatibility and allow large file access
607-
* even if userspace doesn't ask for it explicitly. Some mkfs
608-
* binary needs it. We might want to drop this workaround
609-
* during an unstable branch.
610-
*/
611-
filp->f_flags |= O_LARGEFILE;
612-
filp->f_mode |= FMODE_BUF_RASYNC | FMODE_CAN_ODIRECT;
604+
void *holder;
605+
int ret;
613606

614607
mode = file_to_blk_mode(filp);
615-
handle = bdev_open_by_dev(inode->i_rdev, mode,
616-
mode & BLK_OPEN_EXCL ? filp : NULL, NULL);
617-
if (IS_ERR(handle))
618-
return PTR_ERR(handle);
608+
holder = mode & BLK_OPEN_EXCL ? filp : NULL;
609+
ret = bdev_permission(inode->i_rdev, mode, holder);
610+
if (ret)
611+
return ret;
619612

620-
if (bdev_nowait(handle->bdev))
621-
filp->f_mode |= FMODE_NOWAIT;
613+
bdev = blkdev_get_no_open(inode->i_rdev);
614+
if (!bdev)
615+
return -ENXIO;
622616

623-
filp->f_mapping = handle->bdev->bd_inode->i_mapping;
624-
filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping);
625-
filp->private_data = handle;
626-
return 0;
617+
ret = bdev_open(bdev, mode, holder, NULL, filp);
618+
if (ret)
619+
blkdev_put_no_open(bdev);
620+
return ret;
627621
}
628622

629623
static int blkdev_release(struct inode *inode, struct file *filp)
630624
{
631-
bdev_release(filp->private_data);
625+
if (filp->private_data)
626+
bdev_release(filp->private_data);
632627
return 0;
633628
}
634629

include/linux/blkdev.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,13 +1475,6 @@ extern const struct blk_holder_ops fs_holder_ops;
14751475
(BLK_OPEN_READ | BLK_OPEN_RESTRICT_WRITES | \
14761476
(((flags) & SB_RDONLY) ? 0 : BLK_OPEN_WRITE))
14771477

1478-
/* @bdev_handle will be removed soon. */
1479-
struct bdev_handle {
1480-
struct block_device *bdev;
1481-
void *holder;
1482-
blk_mode_t mode;
1483-
};
1484-
14851478
struct file *bdev_file_open_by_dev(dev_t dev, blk_mode_t mode, void *holder,
14861479
const struct blk_holder_ops *hops);
14871480
struct file *bdev_file_open_by_path(const char *path, blk_mode_t mode,

include/linux/fs.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,12 +1327,6 @@ struct super_block {
13271327
struct list_head s_inodes_wb; /* writeback inodes */
13281328
} __randomize_layout;
13291329

1330-
/* Temporary helper that will go away. */
1331-
static inline struct bdev_handle *sb_bdev_handle(struct super_block *sb)
1332-
{
1333-
return sb->s_bdev_file->private_data;
1334-
}
1335-
13361330
static inline struct user_namespace *i_user_ns(const struct inode *inode)
13371331
{
13381332
return inode->i_sb->s_user_ns;

0 commit comments

Comments
 (0)