@@ -49,6 +49,12 @@ struct block_device *I_BDEV(struct inode *inode)
49
49
}
50
50
EXPORT_SYMBOL (I_BDEV );
51
51
52
+ struct block_device * file_bdev (struct file * bdev_file )
53
+ {
54
+ return I_BDEV (bdev_file -> f_mapping -> host );
55
+ }
56
+ EXPORT_SYMBOL (file_bdev );
57
+
52
58
static void bdev_write_inode (struct block_device * bdev )
53
59
{
54
60
struct inode * inode = bdev -> bd_inode ;
@@ -368,12 +374,12 @@ static struct file_system_type bd_type = {
368
374
};
369
375
370
376
struct super_block * blockdev_superblock __ro_after_init ;
377
+ struct vfsmount * blockdev_mnt __ro_after_init ;
371
378
EXPORT_SYMBOL_GPL (blockdev_superblock );
372
379
373
380
void __init bdev_cache_init (void )
374
381
{
375
382
int err ;
376
- static struct vfsmount * bd_mnt __ro_after_init ;
377
383
378
384
bdev_cachep = kmem_cache_create ("bdev_cache" , sizeof (struct bdev_inode ),
379
385
0 , (SLAB_HWCACHE_ALIGN |SLAB_RECLAIM_ACCOUNT |
@@ -382,10 +388,10 @@ void __init bdev_cache_init(void)
382
388
err = register_filesystem (& bd_type );
383
389
if (err )
384
390
panic ("Cannot register bdev pseudo-fs" );
385
- bd_mnt = kern_mount (& bd_type );
386
- if (IS_ERR (bd_mnt ))
391
+ blockdev_mnt = kern_mount (& bd_type );
392
+ if (IS_ERR (blockdev_mnt ))
387
393
panic ("Cannot create bdev pseudo-fs" );
388
- blockdev_superblock = bd_mnt -> mnt_sb ; /* For writeback */
394
+ blockdev_superblock = blockdev_mnt -> mnt_sb ; /* For writeback */
389
395
}
390
396
391
397
struct block_device * bdev_alloc (struct gendisk * disk , u8 partno )
@@ -696,6 +702,31 @@ static int blkdev_get_part(struct block_device *part, blk_mode_t mode)
696
702
return ret ;
697
703
}
698
704
705
+ int bdev_permission (dev_t dev , blk_mode_t mode , void * holder )
706
+ {
707
+ int ret ;
708
+
709
+ ret = devcgroup_check_permission (DEVCG_DEV_BLOCK ,
710
+ MAJOR (dev ), MINOR (dev ),
711
+ ((mode & BLK_OPEN_READ ) ? DEVCG_ACC_READ : 0 ) |
712
+ ((mode & BLK_OPEN_WRITE ) ? DEVCG_ACC_WRITE : 0 ));
713
+ if (ret )
714
+ return ret ;
715
+
716
+ /* Blocking writes requires exclusive opener */
717
+ if (mode & BLK_OPEN_RESTRICT_WRITES && !holder )
718
+ return - EINVAL ;
719
+
720
+ /*
721
+ * We're using error pointers to indicate to ->release() when we
722
+ * failed to open that block device. Also this doesn't make sense.
723
+ */
724
+ if (WARN_ON_ONCE (IS_ERR (holder )))
725
+ return - EINVAL ;
726
+
727
+ return 0 ;
728
+ }
729
+
699
730
static void blkdev_put_part (struct block_device * part )
700
731
{
701
732
struct block_device * whole = bdev_whole (part );
@@ -775,83 +806,55 @@ static void bdev_claim_write_access(struct block_device *bdev, blk_mode_t mode)
775
806
bdev -> bd_writers ++ ;
776
807
}
777
808
778
- static void bdev_yield_write_access (struct block_device * bdev , blk_mode_t mode )
809
+ static void bdev_yield_write_access (struct file * bdev_file )
779
810
{
811
+ struct block_device * bdev ;
812
+
780
813
if (bdev_allow_write_mounted )
781
814
return ;
782
815
816
+ bdev = file_bdev (bdev_file );
783
817
/* Yield exclusive or shared write access. */
784
- if (mode & BLK_OPEN_RESTRICT_WRITES )
785
- bdev_unblock_writes (bdev );
786
- else if (mode & BLK_OPEN_WRITE )
787
- bdev -> bd_writers -- ;
818
+ if (bdev_file -> f_mode & FMODE_WRITE ) {
819
+ if (bdev_writes_blocked (bdev ))
820
+ bdev_unblock_writes (bdev );
821
+ else
822
+ bdev -> bd_writers -- ;
823
+ }
788
824
}
789
825
790
826
/**
791
- * bdev_open_by_dev - open a block device by device number
792
- * @dev: device number of block device to open
827
+ * bdev_open - open a block device
828
+ * @bdev: block device to open
793
829
* @mode: open mode (BLK_OPEN_*)
794
830
* @holder: exclusive holder identifier
795
831
* @hops: holder operations
832
+ * @bdev_file: file for the block device
796
833
*
797
- * Open the block device described by device number @dev. If @holder is not
798
- * %NULL, the block device is opened with exclusive access. Exclusive opens may
799
- * nest for the same @holder.
800
- *
801
- * Use this interface ONLY if you really do not have anything better - i.e. when
802
- * you are behind a truly sucky interface and all you are given is a device
803
- * number. Everything else should use bdev_open_by_path().
834
+ * Open the block device. If @holder is not %NULL, the block device is opened
835
+ * with exclusive access. Exclusive opens may nest for the same @holder.
804
836
*
805
837
* CONTEXT:
806
838
* Might sleep.
807
839
*
808
840
* RETURNS:
809
- * Handle with a reference to the block_device on success, ERR_PTR(-errno) on
810
- * failure.
841
+ * zero on success, -errno on failure.
811
842
*/
812
- struct bdev_handle * bdev_open_by_dev ( dev_t dev , blk_mode_t mode , void * holder ,
813
- const struct blk_holder_ops * hops )
843
+ int bdev_open ( struct block_device * bdev , blk_mode_t mode , void * holder ,
844
+ const struct blk_holder_ops * hops , struct file * bdev_file )
814
845
{
815
- struct bdev_handle * handle = kmalloc (sizeof (struct bdev_handle ),
816
- GFP_KERNEL );
817
- struct block_device * bdev ;
818
846
bool unblock_events = true;
819
- struct gendisk * disk ;
847
+ struct gendisk * disk = bdev -> bd_disk ;
820
848
int ret ;
821
849
822
- if (!handle )
823
- return ERR_PTR (- ENOMEM );
824
-
825
- ret = devcgroup_check_permission (DEVCG_DEV_BLOCK ,
826
- MAJOR (dev ), MINOR (dev ),
827
- ((mode & BLK_OPEN_READ ) ? DEVCG_ACC_READ : 0 ) |
828
- ((mode & BLK_OPEN_WRITE ) ? DEVCG_ACC_WRITE : 0 ));
829
- if (ret )
830
- goto free_handle ;
831
-
832
- /* Blocking writes requires exclusive opener */
833
- if (mode & BLK_OPEN_RESTRICT_WRITES && !holder ) {
834
- ret = - EINVAL ;
835
- goto free_handle ;
836
- }
837
-
838
- bdev = blkdev_get_no_open (dev );
839
- if (!bdev ) {
840
- ret = - ENXIO ;
841
- goto free_handle ;
842
- }
843
- disk = bdev -> bd_disk ;
844
-
845
850
if (holder ) {
846
851
mode |= BLK_OPEN_EXCL ;
847
852
ret = bd_prepare_to_claim (bdev , holder , hops );
848
853
if (ret )
849
- goto put_blkdev ;
854
+ return ret ;
850
855
} else {
851
- if (WARN_ON_ONCE (mode & BLK_OPEN_EXCL )) {
852
- ret = - EIO ;
853
- goto put_blkdev ;
854
- }
856
+ if (WARN_ON_ONCE (mode & BLK_OPEN_EXCL ))
857
+ return - EIO ;
855
858
}
856
859
857
860
disk_block_events (disk );
@@ -892,70 +895,126 @@ struct bdev_handle *bdev_open_by_dev(dev_t dev, blk_mode_t mode, void *holder,
892
895
893
896
if (unblock_events )
894
897
disk_unblock_events (disk );
895
- handle -> bdev = bdev ;
896
- handle -> holder = holder ;
897
- handle -> mode = mode ;
898
- return handle ;
898
+
899
+ bdev_file -> f_flags |= O_LARGEFILE ;
900
+ bdev_file -> f_mode |= FMODE_BUF_RASYNC | FMODE_CAN_ODIRECT ;
901
+ if (bdev_nowait (bdev ))
902
+ bdev_file -> f_mode |= FMODE_NOWAIT ;
903
+ bdev_file -> f_mapping = bdev -> bd_inode -> i_mapping ;
904
+ bdev_file -> f_wb_err = filemap_sample_wb_err (bdev_file -> f_mapping );
905
+ bdev_file -> private_data = holder ;
906
+
907
+ return 0 ;
899
908
put_module :
900
909
module_put (disk -> fops -> owner );
901
910
abort_claiming :
902
911
if (holder )
903
912
bd_abort_claiming (bdev , holder );
904
913
mutex_unlock (& disk -> open_mutex );
905
914
disk_unblock_events (disk );
906
- put_blkdev :
907
- blkdev_put_no_open (bdev );
908
- free_handle :
909
- kfree (handle );
910
- return ERR_PTR (ret );
915
+ return ret ;
911
916
}
912
- EXPORT_SYMBOL (bdev_open_by_dev );
913
917
914
- /**
915
- * bdev_open_by_path - open a block device by name
916
- * @path: path to the block device to open
917
- * @mode: open mode (BLK_OPEN_*)
918
- * @holder: exclusive holder identifier
919
- * @hops: holder operations
920
- *
921
- * Open the block device described by the device file at @path. If @holder is
922
- * not %NULL, the block device is opened with exclusive access. Exclusive opens
923
- * may nest for the same @holder.
924
- *
925
- * CONTEXT:
926
- * Might sleep.
918
+ /*
919
+ * If BLK_OPEN_WRITE_IOCTL is set then this is a historical quirk
920
+ * associated with the floppy driver where it has allowed ioctls if the
921
+ * file was opened for writing, but does not allow reads or writes.
922
+ * Make sure that this quirk is reflected in @f_flags.
927
923
*
928
- * RETURNS:
929
- * Handle with a reference to the block_device on success, ERR_PTR(-errno) on
930
- * failure.
924
+ * It can also happen if a block device is opened as O_RDWR | O_WRONLY.
931
925
*/
932
- struct bdev_handle * bdev_open_by_path (const char * path , blk_mode_t mode ,
933
- void * holder , const struct blk_holder_ops * hops )
926
+ static unsigned blk_to_file_flags (blk_mode_t mode )
927
+ {
928
+ unsigned int flags = 0 ;
929
+
930
+ if ((mode & (BLK_OPEN_READ | BLK_OPEN_WRITE )) ==
931
+ (BLK_OPEN_READ | BLK_OPEN_WRITE ))
932
+ flags |= O_RDWR ;
933
+ else if (mode & BLK_OPEN_WRITE_IOCTL )
934
+ flags |= O_RDWR | O_WRONLY ;
935
+ else if (mode & BLK_OPEN_WRITE )
936
+ flags |= O_WRONLY ;
937
+ else if (mode & BLK_OPEN_READ )
938
+ flags |= O_RDONLY ; /* homeopathic, because O_RDONLY is 0 */
939
+ else
940
+ WARN_ON_ONCE (true);
941
+
942
+ if (mode & BLK_OPEN_NDELAY )
943
+ flags |= O_NDELAY ;
944
+
945
+ return flags ;
946
+ }
947
+
948
+ struct file * bdev_file_open_by_dev (dev_t dev , blk_mode_t mode , void * holder ,
949
+ const struct blk_holder_ops * hops )
934
950
{
935
- struct bdev_handle * handle ;
951
+ struct file * bdev_file ;
952
+ struct block_device * bdev ;
953
+ unsigned int flags ;
954
+ int ret ;
955
+
956
+ ret = bdev_permission (dev , mode , holder );
957
+ if (ret )
958
+ return ERR_PTR (ret );
959
+
960
+ bdev = blkdev_get_no_open (dev );
961
+ if (!bdev )
962
+ return ERR_PTR (- ENXIO );
963
+
964
+ flags = blk_to_file_flags (mode );
965
+ bdev_file = alloc_file_pseudo_noaccount (bdev -> bd_inode ,
966
+ blockdev_mnt , "" , flags | O_LARGEFILE , & def_blk_fops );
967
+ if (IS_ERR (bdev_file )) {
968
+ blkdev_put_no_open (bdev );
969
+ return bdev_file ;
970
+ }
971
+ ihold (bdev -> bd_inode );
972
+
973
+ ret = bdev_open (bdev , mode , holder , hops , bdev_file );
974
+ if (ret ) {
975
+ /* We failed to open the block device. Let ->release() know. */
976
+ bdev_file -> private_data = ERR_PTR (ret );
977
+ fput (bdev_file );
978
+ return ERR_PTR (ret );
979
+ }
980
+ return bdev_file ;
981
+ }
982
+ EXPORT_SYMBOL (bdev_file_open_by_dev );
983
+
984
+ struct file * bdev_file_open_by_path (const char * path , blk_mode_t mode ,
985
+ void * holder ,
986
+ const struct blk_holder_ops * hops )
987
+ {
988
+ struct file * file ;
936
989
dev_t dev ;
937
990
int error ;
938
991
939
992
error = lookup_bdev (path , & dev );
940
993
if (error )
941
994
return ERR_PTR (error );
942
995
943
- handle = bdev_open_by_dev (dev , mode , holder , hops );
944
- if (!IS_ERR (handle ) && (mode & BLK_OPEN_WRITE ) &&
945
- bdev_read_only (handle -> bdev )) {
946
- bdev_release (handle );
947
- return ERR_PTR (- EACCES );
996
+ file = bdev_file_open_by_dev (dev , mode , holder , hops );
997
+ if (!IS_ERR (file ) && (mode & BLK_OPEN_WRITE )) {
998
+ if (bdev_read_only (file_bdev (file ))) {
999
+ fput (file );
1000
+ file = ERR_PTR (- EACCES );
1001
+ }
948
1002
}
949
1003
950
- return handle ;
1004
+ return file ;
951
1005
}
952
- EXPORT_SYMBOL (bdev_open_by_path );
1006
+ EXPORT_SYMBOL (bdev_file_open_by_path );
953
1007
954
- void bdev_release (struct bdev_handle * handle )
1008
+ void bdev_release (struct file * bdev_file )
955
1009
{
956
- struct block_device * bdev = handle -> bdev ;
1010
+ struct block_device * bdev = file_bdev (bdev_file );
1011
+ void * holder = bdev_file -> private_data ;
957
1012
struct gendisk * disk = bdev -> bd_disk ;
958
1013
1014
+ /* We failed to open that block device. */
1015
+ if (IS_ERR (holder ))
1016
+ goto put_no_open ;
1017
+
959
1018
/*
960
1019
* Sync early if it looks like we're the last one. If someone else
961
1020
* opens the block device between now and the decrement of bd_openers
@@ -967,10 +1026,10 @@ void bdev_release(struct bdev_handle *handle)
967
1026
sync_blockdev (bdev );
968
1027
969
1028
mutex_lock (& disk -> open_mutex );
970
- bdev_yield_write_access (bdev , handle -> mode );
1029
+ bdev_yield_write_access (bdev_file );
971
1030
972
- if (handle -> holder )
973
- bd_end_claim (bdev , handle -> holder );
1031
+ if (holder )
1032
+ bd_end_claim (bdev , holder );
974
1033
975
1034
/*
976
1035
* Trigger event checking and tell drivers to flush MEDIA_CHANGE
@@ -986,10 +1045,9 @@ void bdev_release(struct bdev_handle *handle)
986
1045
mutex_unlock (& disk -> open_mutex );
987
1046
988
1047
module_put (disk -> fops -> owner );
1048
+ put_no_open :
989
1049
blkdev_put_no_open (bdev );
990
- kfree (handle );
991
1050
}
992
- EXPORT_SYMBOL (bdev_release );
993
1051
994
1052
/**
995
1053
* lookup_bdev() - Look up a struct block_device by name.
0 commit comments