Skip to content

Commit 6cf86a0

Browse files
asjkdave
authored andcommitted
btrfs: create a helper function to read the disk super
A part of code from btrfs_scan_one_device() is moved to a new function btrfs_read_disk_super(), so that former function looks cleaner. (In this process it also moves the code which ensures null terminating label). So this creates easy opportunity to merge various duplicate codes on read disk super. Earlier attempt to merge duplicate codes highlighted that there were some issues for which there are duplicate codes (to read disk super), however it was not clear what was the issue. So until we figure that out, its better to keep them in a separate functions. Signed-off-by: Anand Jain <[email protected]> [ use GFP_KERNEL, PAGE_CACHE_ removal related fixups ] Signed-off-by: David Sterba <[email protected]>
1 parent 02da2d7 commit 6cf86a0

File tree

1 file changed

+52
-35
lines changed

1 file changed

+52
-35
lines changed

fs/btrfs/volumes.c

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,56 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
988988
return ret;
989989
}
990990

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+
9911041
/*
9921042
* Look for a btrfs signature on a device. This may be called out of the mount path
9931043
* 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,
9991049
struct btrfs_super_block *disk_super;
10001050
struct block_device *bdev;
10011051
struct page *page;
1002-
void *p;
10031052
int ret = -EINVAL;
10041053
u64 devid;
10051054
u64 transid;
10061055
u64 total_devices;
10071056
u64 bytenr;
1008-
pgoff_t index;
10091057

10101058
/*
10111059
* 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,
10181066
mutex_lock(&uuid_mutex);
10191067

10201068
bdev = blkdev_get_by_path(path, flags, holder);
1021-
10221069
if (IS_ERR(bdev)) {
10231070
ret = PTR_ERR(bdev);
10241071
goto error;
10251072
}
10261073

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))
10451075
goto error_bdev_put;
10461076

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-
10561077
devid = btrfs_stack_device_id(&disk_super->dev_item);
10571078
transid = btrfs_super_generation(disk_super);
10581079
total_devices = btrfs_super_num_devices(disk_super);
10591080

10601081
ret = device_list_add(path, disk_super, devid, fs_devices_ret);
10611082
if (ret > 0) {
10621083
if (disk_super->label[0]) {
1063-
if (disk_super->label[BTRFS_LABEL_SIZE - 1])
1064-
disk_super->label[BTRFS_LABEL_SIZE - 1] = '\0';
10651084
printk(KERN_INFO "BTRFS: device label %s ", disk_super->label);
10661085
} else {
10671086
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,
10731092
if (!ret && fs_devices_ret)
10741093
(*fs_devices_ret)->total_devices = total_devices;
10751094

1076-
error_unmap:
1077-
kunmap(page);
1078-
put_page(page);
1095+
btrfs_release_disk_super(page);
10791096

10801097
error_bdev_put:
10811098
blkdev_put(bdev, flags);

0 commit comments

Comments
 (0)