]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
btrfs: create a helper function to read the disk super
authorAnand Jain <anand.jain@oracle.com>
Sat, 13 Feb 2016 02:01:29 +0000 (10:01 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 15 Feb 2016 16:56:54 +0000 (17:56 +0100)
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 ]
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/volumes.c

index 366b335946fae763e380ed884792df5efe07a2c9..fa119ea8c74bafcb6bcaccb4b1206314699e6ee1 100644 (file)
@@ -987,6 +987,56 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
        return ret;
 }
 
+void btrfs_release_disk_super(struct page *page)
+{
+       kunmap(page);
+       page_cache_release(page);
+}
+
+int btrfs_read_disk_super(struct block_device *bdev, u64 bytenr,
+               struct page **page, struct btrfs_super_block **disk_super)
+{
+       void *p;
+       pgoff_t index;
+
+       /* make sure our super fits in the device */
+       if (bytenr + PAGE_CACHE_SIZE >= i_size_read(bdev->bd_inode))
+               return 1;
+
+       /* make sure our super fits in the page */
+       if (sizeof(**disk_super) > PAGE_CACHE_SIZE)
+               return 1;
+
+       /* make sure our super doesn't straddle pages on disk */
+       index = bytenr >> PAGE_CACHE_SHIFT;
+       if ((bytenr + sizeof(**disk_super) - 1) >> PAGE_CACHE_SHIFT != index)
+               return 1;
+
+       /* pull in the page with our super */
+       *page = read_cache_page_gfp(bdev->bd_inode->i_mapping,
+                                  index, GFP_KERNEL);
+
+       if (IS_ERR_OR_NULL(*page))
+               return 1;
+
+       p = kmap(*page);
+
+       /* align our pointer to the offset of the super block */
+       *disk_super = p + (bytenr & ~PAGE_CACHE_MASK);
+
+       if (btrfs_super_bytenr(*disk_super) != bytenr ||
+           btrfs_super_magic(*disk_super) != BTRFS_MAGIC) {
+               btrfs_release_disk_super(*page);
+               return 1;
+       }
+
+       if ((*disk_super)->label[0] &&
+               (*disk_super)->label[BTRFS_LABEL_SIZE - 1])
+               (*disk_super)->label[BTRFS_LABEL_SIZE - 1] = '\0';
+
+       return 0;
+}
+
 /*
  * Look for a btrfs signature on a device. This may be called out of the mount path
  * and we are not allowed to call set_blocksize during the scan. The superblock
@@ -998,13 +1048,11 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
        struct btrfs_super_block *disk_super;
        struct block_device *bdev;
        struct page *page;
-       void *p;
        int ret = -EINVAL;
        u64 devid;
        u64 transid;
        u64 total_devices;
        u64 bytenr;
-       pgoff_t index;
 
        /*
         * we would like to check all the supers, but that would make
@@ -1017,41 +1065,14 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
        mutex_lock(&uuid_mutex);
 
        bdev = blkdev_get_by_path(path, flags, holder);
-
        if (IS_ERR(bdev)) {
                ret = PTR_ERR(bdev);
                goto error;
        }
 
-       /* make sure our super fits in the device */
-       if (bytenr + PAGE_CACHE_SIZE >= i_size_read(bdev->bd_inode))
-               goto error_bdev_put;
-
-       /* make sure our super fits in the page */
-       if (sizeof(*disk_super) > PAGE_CACHE_SIZE)
-               goto error_bdev_put;
-
-       /* make sure our super doesn't straddle pages on disk */
-       index = bytenr >> PAGE_CACHE_SHIFT;
-       if ((bytenr + sizeof(*disk_super) - 1) >> PAGE_CACHE_SHIFT != index)
-               goto error_bdev_put;
-
-       /* pull in the page with our super */
-       page = read_cache_page_gfp(bdev->bd_inode->i_mapping,
-                                  index, GFP_NOFS);
-
-       if (IS_ERR_OR_NULL(page))
+       if (btrfs_read_disk_super(bdev, bytenr, &page, &disk_super))
                goto error_bdev_put;
 
-       p = kmap(page);
-
-       /* align our pointer to the offset of the super block */
-       disk_super = p + (bytenr & ~PAGE_CACHE_MASK);
-
-       if (btrfs_super_bytenr(disk_super) != bytenr ||
-           btrfs_super_magic(disk_super) != BTRFS_MAGIC)
-               goto error_unmap;
-
        devid = btrfs_stack_device_id(&disk_super->dev_item);
        transid = btrfs_super_generation(disk_super);
        total_devices = btrfs_super_num_devices(disk_super);
@@ -1059,8 +1080,6 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
        ret = device_list_add(path, disk_super, devid, fs_devices_ret);
        if (ret > 0) {
                if (disk_super->label[0]) {
-                       if (disk_super->label[BTRFS_LABEL_SIZE - 1])
-                               disk_super->label[BTRFS_LABEL_SIZE - 1] = '\0';
                        printk(KERN_INFO "BTRFS: device label %s ", disk_super->label);
                } else {
                        printk(KERN_INFO "BTRFS: device fsid %pU ", disk_super->fsid);
@@ -1072,9 +1091,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
        if (!ret && fs_devices_ret)
                (*fs_devices_ret)->total_devices = total_devices;
 
-error_unmap:
-       kunmap(page);
-       page_cache_release(page);
+       btrfs_release_disk_super(page);
 
 error_bdev_put:
        blkdev_put(bdev, flags);