@@ -988,6 +988,56 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
988
988
return ret ;
989
989
}
990
990
991
+ void btrfs_release_disk_super (struct page * page )
992
+ {
993
+ kunmap (page );
994
+ put_page (page );
995
+ }
996
+
997
+ int btrfs_read_disk_super (struct block_device * bdev , u64 bytenr ,
998
+ struct page * * page , struct btrfs_super_block * * disk_super )
999
+ {
1000
+ void * p ;
1001
+ pgoff_t index ;
1002
+
1003
+ /* make sure our super fits in the device */
1004
+ if (bytenr + PAGE_SIZE >= i_size_read (bdev -> bd_inode ))
1005
+ return 1 ;
1006
+
1007
+ /* make sure our super fits in the page */
1008
+ if (sizeof (* * disk_super ) > PAGE_SIZE )
1009
+ return 1 ;
1010
+
1011
+ /* make sure our super doesn't straddle pages on disk */
1012
+ index = bytenr >> PAGE_SHIFT ;
1013
+ if ((bytenr + sizeof (* * disk_super ) - 1 ) >> PAGE_SHIFT != index )
1014
+ return 1 ;
1015
+
1016
+ /* pull in the page with our super */
1017
+ * page = read_cache_page_gfp (bdev -> bd_inode -> i_mapping ,
1018
+ index , GFP_KERNEL );
1019
+
1020
+ if (IS_ERR_OR_NULL (* page ))
1021
+ return 1 ;
1022
+
1023
+ p = kmap (* page );
1024
+
1025
+ /* align our pointer to the offset of the super block */
1026
+ * disk_super = p + (bytenr & ~PAGE_MASK );
1027
+
1028
+ if (btrfs_super_bytenr (* disk_super ) != bytenr ||
1029
+ btrfs_super_magic (* disk_super ) != BTRFS_MAGIC ) {
1030
+ btrfs_release_disk_super (* page );
1031
+ return 1 ;
1032
+ }
1033
+
1034
+ if ((* disk_super )-> label [0 ] &&
1035
+ (* disk_super )-> label [BTRFS_LABEL_SIZE - 1 ])
1036
+ (* disk_super )-> label [BTRFS_LABEL_SIZE - 1 ] = '\0' ;
1037
+
1038
+ return 0 ;
1039
+ }
1040
+
991
1041
/*
992
1042
* Look for a btrfs signature on a device. This may be called out of the mount path
993
1043
* and we are not allowed to call set_blocksize during the scan. The superblock
@@ -999,13 +1049,11 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
999
1049
struct btrfs_super_block * disk_super ;
1000
1050
struct block_device * bdev ;
1001
1051
struct page * page ;
1002
- void * p ;
1003
1052
int ret = - EINVAL ;
1004
1053
u64 devid ;
1005
1054
u64 transid ;
1006
1055
u64 total_devices ;
1007
1056
u64 bytenr ;
1008
- pgoff_t index ;
1009
1057
1010
1058
/*
1011
1059
* we would like to check all the supers, but that would make
@@ -1018,50 +1066,21 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
1018
1066
mutex_lock (& uuid_mutex );
1019
1067
1020
1068
bdev = blkdev_get_by_path (path , flags , holder );
1021
-
1022
1069
if (IS_ERR (bdev )) {
1023
1070
ret = PTR_ERR (bdev );
1024
1071
goto error ;
1025
1072
}
1026
1073
1027
- /* make sure our super fits in the device */
1028
- if (bytenr + PAGE_SIZE >= i_size_read (bdev -> bd_inode ))
1029
- goto error_bdev_put ;
1030
-
1031
- /* make sure our super fits in the page */
1032
- if (sizeof (* disk_super ) > PAGE_SIZE )
1033
- goto error_bdev_put ;
1034
-
1035
- /* make sure our super doesn't straddle pages on disk */
1036
- index = bytenr >> PAGE_SHIFT ;
1037
- if ((bytenr + sizeof (* disk_super ) - 1 ) >> PAGE_SHIFT != index )
1038
- goto error_bdev_put ;
1039
-
1040
- /* pull in the page with our super */
1041
- page = read_cache_page_gfp (bdev -> bd_inode -> i_mapping ,
1042
- index , GFP_NOFS );
1043
-
1044
- if (IS_ERR_OR_NULL (page ))
1074
+ if (btrfs_read_disk_super (bdev , bytenr , & page , & disk_super ))
1045
1075
goto error_bdev_put ;
1046
1076
1047
- p = kmap (page );
1048
-
1049
- /* align our pointer to the offset of the super block */
1050
- disk_super = p + (bytenr & ~PAGE_MASK );
1051
-
1052
- if (btrfs_super_bytenr (disk_super ) != bytenr ||
1053
- btrfs_super_magic (disk_super ) != BTRFS_MAGIC )
1054
- goto error_unmap ;
1055
-
1056
1077
devid = btrfs_stack_device_id (& disk_super -> dev_item );
1057
1078
transid = btrfs_super_generation (disk_super );
1058
1079
total_devices = btrfs_super_num_devices (disk_super );
1059
1080
1060
1081
ret = device_list_add (path , disk_super , devid , fs_devices_ret );
1061
1082
if (ret > 0 ) {
1062
1083
if (disk_super -> label [0 ]) {
1063
- if (disk_super -> label [BTRFS_LABEL_SIZE - 1 ])
1064
- disk_super -> label [BTRFS_LABEL_SIZE - 1 ] = '\0' ;
1065
1084
printk (KERN_INFO "BTRFS: device label %s " , disk_super -> label );
1066
1085
} else {
1067
1086
printk (KERN_INFO "BTRFS: device fsid %pU " , disk_super -> fsid );
@@ -1073,9 +1092,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
1073
1092
if (!ret && fs_devices_ret )
1074
1093
(* fs_devices_ret )-> total_devices = total_devices ;
1075
1094
1076
- error_unmap :
1077
- kunmap (page );
1078
- put_page (page );
1095
+ btrfs_release_disk_super (page );
1079
1096
1080
1097
error_bdev_put :
1081
1098
blkdev_put (bdev , flags );
0 commit comments