Skip to content

Commit

Permalink
btrfs: create a helper function to read the disk super
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Anand Jain authored and David Sterba committed Apr 28, 2016
1 parent 02da2d7 commit 6cf86a0
Showing 1 changed file with 52 additions and 35 deletions.
87 changes: 52 additions & 35 deletions fs/btrfs/volumes.c
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,56 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
return ret;
}

void btrfs_release_disk_super(struct page *page)
{
kunmap(page);
put_page(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_SIZE >= i_size_read(bdev->bd_inode))
return 1;

/* make sure our super fits in the page */
if (sizeof(**disk_super) > PAGE_SIZE)
return 1;

/* make sure our super doesn't straddle pages on disk */
index = bytenr >> PAGE_SHIFT;
if ((bytenr + sizeof(**disk_super) - 1) >> PAGE_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_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
Expand All @@ -999,13 +1049,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
Expand All @@ -1018,50 +1066,21 @@ 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_SIZE >= i_size_read(bdev->bd_inode))
goto error_bdev_put;

/* make sure our super fits in the page */
if (sizeof(*disk_super) > PAGE_SIZE)
goto error_bdev_put;

/* make sure our super doesn't straddle pages on disk */
index = bytenr >> PAGE_SHIFT;
if ((bytenr + sizeof(*disk_super) - 1) >> PAGE_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_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);

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);
Expand All @@ -1073,9 +1092,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);
put_page(page);
btrfs_release_disk_super(page);

error_bdev_put:
blkdev_put(bdev, flags);
Expand Down

0 comments on commit 6cf86a0

Please sign in to comment.