@@ -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+
706724static 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 ;
906907put_module :
907908 module_put (disk -> fops -> owner );
908909abort_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 );
915914free_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}
979982EXPORT_SYMBOL (bdev_file_open_by_dev );
0 commit comments