@@ -2621,8 +2621,6 @@ int __cold open_ctree(struct super_block *sb,
struct btrfs_fs_info *fs_info = btrfs_sb(sb);
struct btrfs_root *tree_root;
struct btrfs_root *chunk_root;
- struct page *super_page;
- u8 *superblock;
int ret;
int err = -EINVAL;
int clear_free_space_tree = 0;
@@ -2816,33 +2814,29 @@ int __cold open_ctree(struct super_block *sb,
/*
* Read super block and check the signature bytes only
*/
- ret = btrfs_read_dev_super(fs_devices->latest_bdev, &super_page);
- if (ret) {
- err = ret;
+ disk_super = btrfs_read_dev_super(fs_devices->latest_bdev);
+ if (IS_ERR(disk_super)) {
+ err = PTR_ERR(disk_super);
goto fail_alloc;
}
- superblock = kmap(super_page);
/*
* Verify the type first, if that or the the checksum value are
* corrupted, we'll find out
*/
- csum_type = btrfs_super_csum_type((struct btrfs_super_block *)
- superblock);
+ csum_type = btrfs_super_csum_type(disk_super);
if (!btrfs_supported_super_csum(csum_type)) {
btrfs_err(fs_info, "unsupported checksum algorithm: %u",
csum_type);
err = -EINVAL;
- kunmap(super_page);
- put_page(super_page);
+ btrfs_release_disk_super(disk_super);
goto fail_alloc;
}
ret = btrfs_init_csum_hash(fs_info, csum_type);
if (ret) {
err = ret;
- kunmap(super_page);
- put_page(super_page);
+ btrfs_release_disk_super(disk_super);
goto fail_alloc;
}
@@ -2850,11 +2844,10 @@ int __cold open_ctree(struct super_block *sb,
* We want to check superblock checksum, the type is stored inside.
* Pass the whole disk block of size BTRFS_SUPER_INFO_SIZE (4k).
*/
- if (btrfs_check_super_csum(fs_info, superblock)) {
+ if (btrfs_check_super_csum(fs_info, (u8 *) disk_super)) {
btrfs_err(fs_info, "superblock checksum mismatch");
err = -EINVAL;
- kunmap(super_page);
- put_page(super_page);
+ btrfs_release_disk_super(disk_super);
goto fail_csum;
}
@@ -2863,9 +2856,8 @@ int __cold open_ctree(struct super_block *sb,
* following bytes up to INFO_SIZE, the checksum is calculated from
* the whole block of INFO_SIZE
*/
- memcpy(fs_info->super_copy, superblock, sizeof(*fs_info->super_copy));
- kunmap(super_page);
- put_page(super_page);
+ memcpy(fs_info->super_copy, disk_super, sizeof(*fs_info->super_copy));
+ btrfs_release_disk_super(disk_super);
disk_super = fs_info->super_copy;
@@ -3362,8 +3354,8 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate)
put_bh(bh);
}
-int btrfs_read_dev_one_super(struct block_device *bdev, int copy_num,
- struct page **super_page)
+struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev,
+ int copy_num)
{
struct btrfs_super_block *super;
struct page *page;
@@ -3372,33 +3364,28 @@ int btrfs_read_dev_one_super(struct block_device *bdev, int copy_num,
bytenr = btrfs_sb_offset(copy_num);
if (bytenr + BTRFS_SUPER_INFO_SIZE >= i_size_read(bdev->bd_inode))
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
page = read_cache_page_gfp(mapping, bytenr >> PAGE_SHIFT, GFP_NOFS);
if (IS_ERR_OR_NULL(page))
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- super = kmap(page);
+ super = kmap(page) + offset_in_page(bytenr);
if (btrfs_super_bytenr(super) != bytenr ||
btrfs_super_magic(super) != BTRFS_MAGIC) {
- kunmap(page);
- put_page(page);
- return -EINVAL;
+ btrfs_release_disk_super(super);
+ return ERR_PTR(-EINVAL);
}
- kunmap(page);
- *super_page = page;
- return 0;
+ return super;
}
-int btrfs_read_dev_super(struct block_device *bdev, struct page **page)
+struct btrfs_super_block *btrfs_read_dev_super(struct block_device *bdev)
{
- struct page *latest = NULL;
- struct btrfs_super_block *super;
+ struct btrfs_super_block *super, *latest = NULL;
int i;
u64 transid = 0;
- int ret = -EINVAL;
/* we would like to check all the supers, but that would make
* a btrfs mount succeed after a mkfs from a different FS.
@@ -3406,25 +3393,20 @@ int btrfs_read_dev_super(struct block_device *bdev, struct page **page)
* later supers, using BTRFS_SUPER_MIRROR_MAX instead
*/
for (i = 0; i < 1; i++) {
- ret = btrfs_read_dev_one_super(bdev, i, page);
- if (ret)
+ super = btrfs_read_dev_one_super(bdev, i);
+ if (IS_ERR(super))
continue;
- super = kmap(*page);
-
if (!latest || btrfs_super_generation(super) > transid) {
- if (latest) {
- kunmap(latest);
- put_page(latest);
- }
- latest = *page;
+ if (latest)
+ btrfs_release_disk_super(super);
+
+ latest = super;
transid = btrfs_super_generation(super);
}
-
- kunmap(*page);
}
- return ret;
+ return super;
}
/*
@@ -54,9 +54,9 @@ int __cold open_ctree(struct super_block *sb,
char *options);
void __cold close_ctree(struct btrfs_fs_info *fs_info);
int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors);
-int btrfs_read_dev_super(struct block_device *bdev, struct page **super_page);
-int btrfs_read_dev_one_super(struct block_device *bdev, int copy_num,
- struct page **super_page);
+struct btrfs_super_block *btrfs_read_dev_super(struct block_device *bdev);
+struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev,
+ int copy_num);
int btrfs_commit_super(struct btrfs_fs_info *fs_info);
struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
struct btrfs_key *key);
@@ -499,7 +499,7 @@ static struct btrfs_fs_devices *find_fsid_with_metadata_uuid(
static int
btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder,
int flush, struct block_device **bdev,
- struct page **super_page)
+ struct btrfs_super_block **disk_super)
{
int ret;
@@ -518,8 +518,9 @@ btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder,
goto error;
}
invalidate_bdev(*bdev);
- ret = btrfs_read_dev_super(*bdev, super_page);
- if (ret) {
+ *disk_super = btrfs_read_dev_super(*bdev);
+ if (IS_ERR(*disk_super)) {
+ ret = PTR_ERR(*disk_super);
blkdev_put(*bdev, flags);
goto error;
}
@@ -608,7 +609,6 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
{
struct request_queue *q;
struct block_device *bdev;
- struct page *super_page;
struct btrfs_super_block *disk_super;
u64 devid;
int ret;
@@ -619,11 +619,10 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
return -EINVAL;
ret = btrfs_get_bdev_and_sb(device->name->str, flags, holder, 1,
- &bdev, &super_page);
+ &bdev, &disk_super);
if (ret)
return ret;
- disk_super = kmap(super_page);
devid = btrfs_stack_device_id(&disk_super->dev_item);
if (devid != device->devid)
goto error_free_page;
@@ -664,14 +663,12 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
fs_devices->rw_devices++;
list_add_tail(&device->dev_alloc_list, &fs_devices->alloc_list);
}
- kunmap(super_page);
- put_page(super_page);
+ btrfs_release_disk_super(disk_super);
return 0;
error_free_page:
- kunmap(super_page);
- put_page(super_page);
+ btrfs_release_disk_super(disk_super);
blkdev_put(bdev, flags);
return -EINVAL;
@@ -1246,8 +1243,10 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
return ret;
}
-void btrfs_release_disk_super(struct page *page)
+void btrfs_release_disk_super(struct btrfs_super_block *super)
{
+ struct page *page = kmap_to_page(super);
+
kunmap(page);
put_page(page);
}
@@ -1286,7 +1285,7 @@ static int btrfs_read_disk_super(struct block_device *bdev, u64 bytenr,
if (btrfs_super_bytenr(*disk_super) != bytenr ||
btrfs_super_magic(*disk_super) != BTRFS_MAGIC) {
- btrfs_release_disk_super(*page);
+ btrfs_release_disk_super(p);
return 1;
}
@@ -1349,7 +1348,7 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, fmode_t flags,
btrfs_free_stale_devices(path, device);
}
- btrfs_release_disk_super(page);
+ btrfs_release_disk_super(disk_super);
error_bdev_put:
blkdev_put(bdev, flags);
@@ -2208,15 +2207,14 @@ static struct btrfs_device *btrfs_find_device_by_path(
u64 devid;
u8 *dev_uuid;
struct block_device *bdev;
- struct page *super_page;
struct btrfs_device *device;
ret = btrfs_get_bdev_and_sb(device_path, FMODE_READ,
fs_info->bdev_holder, 0, &bdev,
- &super_page);
+ &disk_super);
if (ret)
return ERR_PTR(ret);
- disk_super = kmap(super_page);
+
devid = btrfs_stack_device_id(&disk_super->dev_item);
dev_uuid = disk_super->dev_item.uuid;
if (btrfs_fs_incompat(fs_info, METADATA_UUID))
@@ -2226,8 +2224,7 @@ static struct btrfs_device *btrfs_find_device_by_path(
device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
disk_super->fsid, true);
- kunmap(super_page);
- put_page(super_page);
+ btrfs_release_disk_super(disk_super);
if (!device)
device = ERR_PTR(-ENOENT);
blkdev_put(bdev, FMODE_READ);
@@ -7328,20 +7325,19 @@ void btrfs_scratch_superblocks(struct block_device *bdev, const char *device_pat
for (copy_num = 0; copy_num < BTRFS_SUPER_MIRROR_MAX;
copy_num++) {
- u64 bytenr = btrfs_sb_offset(copy_num);
struct page *page;
- if (btrfs_read_dev_one_super(bdev, copy_num, &page))
+ disk_super = btrfs_read_dev_one_super(bdev, copy_num);
+ if (IS_ERR(disk_super))
continue;
- disk_super = kmap(page) + offset_in_page(bytenr);
memset(&disk_super->magic, 0, sizeof(disk_super->magic));
- kunmap(page);
+ page = kmap_to_page(disk_super);
set_page_dirty(page);
lock_page(page); /* write_on_page() unlocks the page */
write_one_page(page);
- put_page(page);
+ btrfs_release_disk_super(disk_super);
}
@@ -481,7 +481,7 @@ int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans,
int btrfs_remove_chunk(struct btrfs_trans_handle *trans, u64 chunk_offset);
struct extent_map *btrfs_get_chunk_map(struct btrfs_fs_info *fs_info,
u64 logical, u64 length);
-void btrfs_release_disk_super(struct page *page);
+void btrfs_release_disk_super(struct btrfs_super_block *super);
static inline void btrfs_dev_stat_inc(struct btrfs_device *dev,
int index)
Let btrfs_read_dev_super() return a 'struct btrfs_super_block' and btrfs_release_disk_super() take a 'struct btrfs_disk_super' as well. Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> --- fs/btrfs/disk-io.c | 72 +++++++++++++++++----------------------------- fs/btrfs/disk-io.h | 6 ++-- fs/btrfs/volumes.c | 42 ++++++++++++--------------- fs/btrfs/volumes.h | 2 +- 4 files changed, 50 insertions(+), 72 deletions(-)