mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2026-01-27 12:47:24 +01:00
btrfs: merge btrfs_read_dev_one_super() into btrfs_read_disk_super()
We have two functions to read a super block from a block device: - btrfs_read_dev_one_super() Exported from disk-io.c - btrfs_read_disk_super() Local to volumes.c And they have some minor differences: - btrfs_read_dev_one_super() uses @copy_num Meanwhile btrfs_read_disk_super() relies on the physical and expected bytenr passed from the caller. The parameter list of btrfs_read_dev_one_super() is more user friendly. - btrfs_read_disk_super() makes sure the label is NUL terminated We do not need two different functions doing the same job, so merge the behavior into btrfs_read_disk_super() by: - Remove btrfs_read_dev_one_super() - Export btrfs_read_disk_super() The name pairs with btrfs_release_disk_super() perfectly. - Change the parameter list of btrfs_read_disk_super() to mimic btrfs_read_dev_one_super() All existing callers are calculating the physical address and expect bytenr before calling btrfs_read_disk_super() already. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
13ae88706a
commit
63f32b7b5d
|
|
@ -3712,57 +3712,6 @@ static void btrfs_end_super_write(struct bio *bio)
|
|||
bio_put(bio);
|
||||
}
|
||||
|
||||
struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev,
|
||||
int copy_num, bool drop_cache)
|
||||
{
|
||||
struct btrfs_super_block *super;
|
||||
struct page *page;
|
||||
u64 bytenr, bytenr_orig;
|
||||
struct address_space *mapping = bdev->bd_mapping;
|
||||
int ret;
|
||||
|
||||
bytenr_orig = btrfs_sb_offset(copy_num);
|
||||
ret = btrfs_sb_log_location_bdev(bdev, copy_num, READ, &bytenr);
|
||||
if (ret == -ENOENT)
|
||||
return ERR_PTR(-EINVAL);
|
||||
else if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
if (bytenr + BTRFS_SUPER_INFO_SIZE >= bdev_nr_bytes(bdev))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (drop_cache) {
|
||||
/* This should only be called with the primary sb. */
|
||||
ASSERT(copy_num == 0);
|
||||
|
||||
/*
|
||||
* Drop the page of the primary superblock, so later read will
|
||||
* always read from the device.
|
||||
*/
|
||||
invalidate_inode_pages2_range(mapping,
|
||||
bytenr >> PAGE_SHIFT,
|
||||
(bytenr + BTRFS_SUPER_INFO_SIZE) >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
page = read_cache_page_gfp(mapping, bytenr >> PAGE_SHIFT, GFP_NOFS);
|
||||
if (IS_ERR(page))
|
||||
return ERR_CAST(page);
|
||||
|
||||
super = page_address(page);
|
||||
if (btrfs_super_magic(super) != BTRFS_MAGIC) {
|
||||
btrfs_release_disk_super(super);
|
||||
return ERR_PTR(-ENODATA);
|
||||
}
|
||||
|
||||
if (btrfs_super_bytenr(super) != bytenr_orig) {
|
||||
btrfs_release_disk_super(super);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return super;
|
||||
}
|
||||
|
||||
|
||||
struct btrfs_super_block *btrfs_read_dev_super(struct block_device *bdev)
|
||||
{
|
||||
struct btrfs_super_block *super, *latest = NULL;
|
||||
|
|
@ -3775,7 +3724,7 @@ struct btrfs_super_block *btrfs_read_dev_super(struct block_device *bdev)
|
|||
* later supers, using BTRFS_SUPER_MIRROR_MAX instead
|
||||
*/
|
||||
for (i = 0; i < 1; i++) {
|
||||
super = btrfs_read_dev_one_super(bdev, i, false);
|
||||
super = btrfs_read_disk_super(bdev, i, false);
|
||||
if (IS_ERR(super))
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -59,8 +59,6 @@ int btrfs_validate_super(const struct btrfs_fs_info *fs_info,
|
|||
int btrfs_check_features(struct btrfs_fs_info *fs_info, bool is_rw_mount);
|
||||
int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors);
|
||||
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, bool drop_cache);
|
||||
int btrfs_commit_super(struct btrfs_fs_info *fs_info);
|
||||
struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
|
||||
const struct btrfs_key *key);
|
||||
|
|
|
|||
|
|
@ -2296,7 +2296,7 @@ static int check_dev_super(struct btrfs_device *dev)
|
|||
return 0;
|
||||
|
||||
/* Only need to check the primary super block. */
|
||||
sb = btrfs_read_dev_one_super(dev->bdev, 0, true);
|
||||
sb = btrfs_read_disk_super(dev->bdev, 0, true);
|
||||
if (IS_ERR(sb))
|
||||
return PTR_ERR(sb);
|
||||
|
||||
|
|
|
|||
|
|
@ -1325,48 +1325,58 @@ void btrfs_release_disk_super(struct btrfs_super_block *super)
|
|||
put_page(page);
|
||||
}
|
||||
|
||||
static struct btrfs_super_block *btrfs_read_disk_super(struct block_device *bdev,
|
||||
u64 bytenr, u64 bytenr_orig)
|
||||
struct btrfs_super_block *btrfs_read_disk_super(struct block_device *bdev,
|
||||
int copy_num, bool drop_cache)
|
||||
{
|
||||
struct btrfs_super_block *disk_super;
|
||||
struct btrfs_super_block *super;
|
||||
struct page *page;
|
||||
void *p;
|
||||
pgoff_t index;
|
||||
u64 bytenr, bytenr_orig;
|
||||
struct address_space *mapping = bdev->bd_mapping;
|
||||
int ret;
|
||||
|
||||
/* make sure our super fits in the device */
|
||||
if (bytenr + PAGE_SIZE >= bdev_nr_bytes(bdev))
|
||||
bytenr_orig = btrfs_sb_offset(copy_num);
|
||||
ret = btrfs_sb_log_location_bdev(bdev, copy_num, READ, &bytenr);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOENT)
|
||||
ret = -EINVAL;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (bytenr + BTRFS_SUPER_INFO_SIZE >= bdev_nr_bytes(bdev))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* make sure our super fits in the page */
|
||||
if (sizeof(*disk_super) > PAGE_SIZE)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (drop_cache) {
|
||||
/* This should only be called with the primary sb. */
|
||||
ASSERT(copy_num == 0);
|
||||
|
||||
/* make sure our super doesn't straddle pages on disk */
|
||||
index = bytenr >> PAGE_SHIFT;
|
||||
if ((bytenr + sizeof(*disk_super) - 1) >> PAGE_SHIFT != index)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* pull in the page with our super */
|
||||
page = read_cache_page_gfp(bdev->bd_mapping, index, GFP_KERNEL);
|
||||
/*
|
||||
* Drop the page of the primary superblock, so later read will
|
||||
* always read from the device.
|
||||
*/
|
||||
invalidate_inode_pages2_range(mapping, bytenr >> PAGE_SHIFT,
|
||||
(bytenr + BTRFS_SUPER_INFO_SIZE) >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
page = read_cache_page_gfp(mapping, bytenr >> PAGE_SHIFT, GFP_NOFS);
|
||||
if (IS_ERR(page))
|
||||
return ERR_CAST(page);
|
||||
|
||||
p = page_address(page);
|
||||
|
||||
/* align our pointer to the offset of the super block */
|
||||
disk_super = p + offset_in_page(bytenr);
|
||||
|
||||
if (btrfs_super_bytenr(disk_super) != bytenr_orig ||
|
||||
btrfs_super_magic(disk_super) != BTRFS_MAGIC) {
|
||||
btrfs_release_disk_super(p);
|
||||
super = page_address(page);
|
||||
if (btrfs_super_magic(super) != BTRFS_MAGIC ||
|
||||
btrfs_super_bytenr(super) != bytenr_orig) {
|
||||
btrfs_release_disk_super(super);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (disk_super->label[0] && disk_super->label[BTRFS_LABEL_SIZE - 1])
|
||||
disk_super->label[BTRFS_LABEL_SIZE - 1] = 0;
|
||||
/*
|
||||
* Make sure the last byte of label is properly NUL termiated. We use
|
||||
* '%s' to print the label, if not properly NUL termiated we can access
|
||||
* beyond the label.
|
||||
*/
|
||||
if (super->label[0] && super->label[BTRFS_LABEL_SIZE - 1])
|
||||
super->label[BTRFS_LABEL_SIZE - 1] = 0;
|
||||
|
||||
return disk_super;
|
||||
return super;
|
||||
}
|
||||
|
||||
int btrfs_forget_devices(dev_t devt)
|
||||
|
|
@ -1437,9 +1447,7 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags,
|
|||
bool new_device_added = false;
|
||||
struct btrfs_device *device = NULL;
|
||||
struct file *bdev_file;
|
||||
u64 bytenr;
|
||||
dev_t devt;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&uuid_mutex);
|
||||
|
||||
|
|
@ -1457,20 +1465,7 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags,
|
|||
if (IS_ERR(bdev_file))
|
||||
return ERR_CAST(bdev_file);
|
||||
|
||||
/*
|
||||
* We would like to check all the super blocks, but doing so would
|
||||
* allow a mount to succeed after a mkfs from a different filesystem.
|
||||
* Currently, recovery from a bad primary btrfs superblock is done
|
||||
* using the userspace command 'btrfs check --super'.
|
||||
*/
|
||||
ret = btrfs_sb_log_location_bdev(file_bdev(bdev_file), 0, READ, &bytenr);
|
||||
if (ret) {
|
||||
device = ERR_PTR(ret);
|
||||
goto error_bdev_put;
|
||||
}
|
||||
|
||||
disk_super = btrfs_read_disk_super(file_bdev(bdev_file), bytenr,
|
||||
btrfs_sb_offset(0));
|
||||
disk_super = btrfs_read_disk_super(file_bdev(bdev_file), 0, false);
|
||||
if (IS_ERR(disk_super)) {
|
||||
device = ERR_CAST(disk_super);
|
||||
goto error_bdev_put;
|
||||
|
|
@ -2136,7 +2131,7 @@ static void btrfs_scratch_superblock(struct btrfs_fs_info *fs_info,
|
|||
const u64 bytenr = btrfs_sb_offset(copy_num);
|
||||
int ret;
|
||||
|
||||
disk_super = btrfs_read_disk_super(bdev, bytenr, bytenr);
|
||||
disk_super = btrfs_read_disk_super(bdev, copy_num, false);
|
||||
if (IS_ERR(disk_super))
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -785,6 +785,8 @@ struct btrfs_chunk_map *btrfs_find_chunk_map_nolock(struct btrfs_fs_info *fs_inf
|
|||
struct btrfs_chunk_map *btrfs_get_chunk_map(struct btrfs_fs_info *fs_info,
|
||||
u64 logical, u64 length);
|
||||
void btrfs_remove_chunk_map(struct btrfs_fs_info *fs_info, struct btrfs_chunk_map *map);
|
||||
struct btrfs_super_block *btrfs_read_disk_super(struct block_device *bdev,
|
||||
int copy_num, bool drop_cache);
|
||||
void btrfs_release_disk_super(struct btrfs_super_block *super);
|
||||
|
||||
static inline void btrfs_dev_stat_inc(struct btrfs_device *dev,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user