提交 6cf86a00 编写于 作者: A Anand Jain 提交者: David Sterba

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: NAnand Jain <anand.jain@oracle.com>
[ use GFP_KERNEL, PAGE_CACHE_ removal related fixups ]
Signed-off-by: NDavid Sterba <dsterba@suse.com>
上级 02da2d72
...@@ -988,6 +988,56 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices, ...@@ -988,6 +988,56 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
return ret; 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 * 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 * 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,13 +1049,11 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
struct btrfs_super_block *disk_super; struct btrfs_super_block *disk_super;
struct block_device *bdev; struct block_device *bdev;
struct page *page; struct page *page;
void *p;
int ret = -EINVAL; int ret = -EINVAL;
u64 devid; u64 devid;
u64 transid; u64 transid;
u64 total_devices; u64 total_devices;
u64 bytenr; u64 bytenr;
pgoff_t index;
/* /*
* we would like to check all the supers, but that would make * 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,41 +1066,14 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
mutex_lock(&uuid_mutex); mutex_lock(&uuid_mutex);
bdev = blkdev_get_by_path(path, flags, holder); bdev = blkdev_get_by_path(path, flags, holder);
if (IS_ERR(bdev)) { if (IS_ERR(bdev)) {
ret = PTR_ERR(bdev); ret = PTR_ERR(bdev);
goto error; goto error;
} }
/* make sure our super fits in the device */ if (btrfs_read_disk_super(bdev, bytenr, &page, &disk_super))
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))
goto error_bdev_put; 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); devid = btrfs_stack_device_id(&disk_super->dev_item);
transid = btrfs_super_generation(disk_super); transid = btrfs_super_generation(disk_super);
total_devices = btrfs_super_num_devices(disk_super); 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,8 +1081,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); ret = device_list_add(path, disk_super, devid, fs_devices_ret);
if (ret > 0) { if (ret > 0) {
if (disk_super->label[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); printk(KERN_INFO "BTRFS: device label %s ", disk_super->label);
} else { } else {
printk(KERN_INFO "BTRFS: device fsid %pU ", disk_super->fsid); 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,9 +1092,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
if (!ret && fs_devices_ret) if (!ret && fs_devices_ret)
(*fs_devices_ret)->total_devices = total_devices; (*fs_devices_ret)->total_devices = total_devices;
error_unmap: btrfs_release_disk_super(page);
kunmap(page);
put_page(page);
error_bdev_put: error_bdev_put:
blkdev_put(bdev, flags); blkdev_put(bdev, flags);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册