aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnand Jain <anand.jain@oracle.com>2016-02-12 21:01:29 -0500
committerDavid Sterba <dsterba@suse.com>2016-04-28 04:59:04 -0400
commit6cf86a006be9f2a77434d5a06ea289719815ad7c (patch)
tree169d42512bc7185e91bd03ab3ea95f5caf8f9c23
parent02da2d72174c61988eb4456b53f405e3ebdebce4 (diff)
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 <anand.jain@oracle.com> [ use GFP_KERNEL, PAGE_CACHE_ removal related fixups ] Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/volumes.c87
1 files changed, 52 insertions, 35 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index bd0f45fb38c4..5006683283ae 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -988,6 +988,56 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
988 return ret; 988 return ret;
989} 989}
990 990
991void btrfs_release_disk_super(struct page *page)
992{
993 kunmap(page);
994 put_page(page);
995}
996
997int 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 * Look for a btrfs signature on a device. This may be called out of the mount path 1042 * Look for a btrfs signature on a device. This may be called out of the mount path
993 * and we are not allowed to call set_blocksize during the scan. The superblock 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 struct btrfs_super_block *disk_super; 1049 struct btrfs_super_block *disk_super;
1000 struct block_device *bdev; 1050 struct block_device *bdev;
1001 struct page *page; 1051 struct page *page;
1002 void *p;
1003 int ret = -EINVAL; 1052 int ret = -EINVAL;
1004 u64 devid; 1053 u64 devid;
1005 u64 transid; 1054 u64 transid;
1006 u64 total_devices; 1055 u64 total_devices;
1007 u64 bytenr; 1056 u64 bytenr;
1008 pgoff_t index;
1009 1057
1010 /* 1058 /*
1011 * we would like to check all the supers, but that would make 1059 * we would like to check all the supers, but that would make
@@ -1018,41 +1066,14 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
1018 mutex_lock(&uuid_mutex); 1066 mutex_lock(&uuid_mutex);
1019 1067
1020 bdev = blkdev_get_by_path(path, flags, holder); 1068 bdev = blkdev_get_by_path(path, flags, holder);
1021
1022 if (IS_ERR(bdev)) { 1069 if (IS_ERR(bdev)) {
1023 ret = PTR_ERR(bdev); 1070 ret = PTR_ERR(bdev);
1024 goto error; 1071 goto error;
1025 } 1072 }
1026 1073
1027 /* make sure our super fits in the device */ 1074 if (btrfs_read_disk_super(bdev, bytenr, &page, &disk_super))
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))
1045 goto error_bdev_put; 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 devid = btrfs_stack_device_id(&disk_super->dev_item); 1077 devid = btrfs_stack_device_id(&disk_super->dev_item);
1057 transid = btrfs_super_generation(disk_super); 1078 transid = btrfs_super_generation(disk_super);
1058 total_devices = btrfs_super_num_devices(disk_super); 1079 total_devices = btrfs_super_num_devices(disk_super);
@@ -1060,8 +1081,6 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
1060 ret = device_list_add(path, disk_super, devid, fs_devices_ret); 1081 ret = device_list_add(path, disk_super, devid, fs_devices_ret);
1061 if (ret > 0) { 1082 if (ret > 0) {
1062 if (disk_super->label[0]) { 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 printk(KERN_INFO "BTRFS: device label %s ", disk_super->label); 1084 printk(KERN_INFO "BTRFS: device label %s ", disk_super->label);
1066 } else { 1085 } else {
1067 printk(KERN_INFO "BTRFS: device fsid %pU ", disk_super->fsid); 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 if (!ret && fs_devices_ret) 1092 if (!ret && fs_devices_ret)
1074 (*fs_devices_ret)->total_devices = total_devices; 1093 (*fs_devices_ret)->total_devices = total_devices;
1075 1094
1076error_unmap: 1095 btrfs_release_disk_super(page);
1077 kunmap(page);
1078 put_page(page);
1079 1096
1080error_bdev_put: 1097error_bdev_put:
1081 blkdev_put(bdev, flags); 1098 blkdev_put(bdev, flags);