mirror of
https://github.com/kdave/btrfs-progs
synced 2024-12-23 14:45:19 +00:00
btrfs-progs: Allow btrfs_read_dev_super() to read all 3 super for super_recover.
Btrfs-progs superblock checksum check is somewhat too restricted for super-recover, since current btrfs-progs will only read the 1st superblock and if you need super-recover the 1st superblock is possibly already damaged. The fix is introducing super_recover parameter for btrfs_read_dev_super() and callers to allow scan backup superblocks if needed. Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.cz>
This commit is contained in:
parent
bc70abad8c
commit
23d7f6d9dc
@ -82,7 +82,7 @@ static struct btrfs_root *open_ctree_broken(int fd, const char *device)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = btrfs_scan_fs_devices(fd, device, &fs_devices, 0, 1);
|
||||
ret = btrfs_scan_fs_devices(fd, device, &fs_devices, 0, 1, 1);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@ -94,7 +94,7 @@ static struct btrfs_root *open_ctree_broken(int fd, const char *device)
|
||||
|
||||
disk_super = fs_info->super_copy;
|
||||
ret = btrfs_read_dev_super(fs_devices->latest_bdev,
|
||||
disk_super, fs_info->super_bytenr);
|
||||
disk_super, fs_info->super_bytenr, 1);
|
||||
if (ret) {
|
||||
printk("No valid btrfs found\n");
|
||||
goto out_devices;
|
||||
|
@ -1281,7 +1281,7 @@ open_ctree_with_broken_chunk(struct recover_control *rc)
|
||||
|
||||
disk_super = fs_info->super_copy;
|
||||
ret = btrfs_read_dev_super(fs_info->fs_devices->latest_bdev,
|
||||
disk_super, fs_info->super_bytenr);
|
||||
disk_super, fs_info->super_bytenr, 1);
|
||||
if (ret) {
|
||||
fprintf(stderr, "No valid btrfs found\n");
|
||||
goto out_devices;
|
||||
@ -1347,7 +1347,7 @@ static int recover_prepare(struct recover_control *rc, char *path)
|
||||
goto fail_close_fd;
|
||||
}
|
||||
|
||||
ret = btrfs_read_dev_super(fd, sb, BTRFS_SUPER_INFO_OFFSET);
|
||||
ret = btrfs_read_dev_super(fd, sb, BTRFS_SUPER_INFO_OFFSET, 1);
|
||||
if (ret) {
|
||||
fprintf(stderr, "read super block error\n");
|
||||
goto fail_free_sb;
|
||||
@ -1366,7 +1366,7 @@ static int recover_prepare(struct recover_control *rc, char *path)
|
||||
goto fail_free_sb;
|
||||
}
|
||||
|
||||
ret = btrfs_scan_fs_devices(fd, path, &fs_devices, 0, 1);
|
||||
ret = btrfs_scan_fs_devices(fd, path, &fs_devices, 0, 1, 1);
|
||||
if (ret)
|
||||
goto fail_free_sb;
|
||||
|
||||
|
@ -513,7 +513,7 @@ static int dev_to_fsid(char *dev, __u8 *fsid)
|
||||
|
||||
disk_super = (struct btrfs_super_block *)buf;
|
||||
ret = btrfs_read_dev_super(fd, disk_super,
|
||||
BTRFS_SUPER_INFO_OFFSET);
|
||||
BTRFS_SUPER_INFO_OFFSET, 0);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
17
disk-io.c
17
disk-io.c
@ -992,7 +992,7 @@ void btrfs_cleanup_all_caches(struct btrfs_fs_info *fs_info)
|
||||
|
||||
int btrfs_scan_fs_devices(int fd, const char *path,
|
||||
struct btrfs_fs_devices **fs_devices,
|
||||
u64 sb_bytenr, int run_ioctl)
|
||||
u64 sb_bytenr, int run_ioctl, int super_recover)
|
||||
{
|
||||
u64 total_devs;
|
||||
int ret;
|
||||
@ -1000,7 +1000,7 @@ int btrfs_scan_fs_devices(int fd, const char *path,
|
||||
sb_bytenr = BTRFS_SUPER_INFO_OFFSET;
|
||||
|
||||
ret = btrfs_scan_one_device(fd, path, fs_devices,
|
||||
&total_devs, sb_bytenr);
|
||||
&total_devs, sb_bytenr, super_recover);
|
||||
if (ret) {
|
||||
fprintf(stderr, "No valid Btrfs found on %s\n", path);
|
||||
return ret;
|
||||
@ -1088,7 +1088,8 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path,
|
||||
fs_info->on_restoring = 1;
|
||||
|
||||
ret = btrfs_scan_fs_devices(fp, path, &fs_devices, sb_bytenr,
|
||||
!(flags & OPEN_CTREE_RECOVER_SUPER));
|
||||
!(flags & OPEN_CTREE_RECOVER_SUPER),
|
||||
(flags & OPEN_CTREE_RECOVER_SUPER));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@ -1108,9 +1109,9 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path,
|
||||
disk_super = fs_info->super_copy;
|
||||
if (!(flags & OPEN_CTREE_RECOVER_SUPER))
|
||||
ret = btrfs_read_dev_super(fs_devices->latest_bdev,
|
||||
disk_super, sb_bytenr);
|
||||
disk_super, sb_bytenr, 1);
|
||||
else
|
||||
ret = btrfs_read_dev_super(fp, disk_super, sb_bytenr);
|
||||
ret = btrfs_read_dev_super(fp, disk_super, sb_bytenr, 0);
|
||||
if (ret) {
|
||||
printk("No valid btrfs found\n");
|
||||
goto out_devices;
|
||||
@ -1194,13 +1195,15 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
||||
return info->fs_root;
|
||||
}
|
||||
|
||||
int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr)
|
||||
int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr,
|
||||
int super_recover)
|
||||
{
|
||||
u8 fsid[BTRFS_FSID_SIZE];
|
||||
int fsid_is_initialized = 0;
|
||||
struct btrfs_super_block buf;
|
||||
int i;
|
||||
int ret;
|
||||
int max_super = super_recover ? BTRFS_SUPER_MIRROR_MAX : 1;
|
||||
u64 transid = 0;
|
||||
u64 bytenr;
|
||||
|
||||
@ -1224,7 +1227,7 @@ int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr)
|
||||
* later supers, using BTRFS_SUPER_MIRROR_MAX instead
|
||||
*/
|
||||
|
||||
for (i = 0; i < 1; i++) {
|
||||
for (i = 0; i < max_super; i++) {
|
||||
bytenr = btrfs_sb_offset(i);
|
||||
ret = pread64(fd, &buf, sizeof(buf), bytenr);
|
||||
if (ret < sizeof(buf))
|
||||
|
@ -68,7 +68,7 @@ void btrfs_release_all_roots(struct btrfs_fs_info *fs_info);
|
||||
void btrfs_cleanup_all_caches(struct btrfs_fs_info *fs_info);
|
||||
int btrfs_scan_fs_devices(int fd, const char *path,
|
||||
struct btrfs_fs_devices **fs_devices, u64 sb_bytenr,
|
||||
int run_ioctl);
|
||||
int run_ioctl, int super_recover);
|
||||
int btrfs_setup_chunk_tree_and_device_map(struct btrfs_fs_info *fs_info);
|
||||
|
||||
struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr,
|
||||
@ -82,7 +82,8 @@ int close_ctree(struct btrfs_root *root);
|
||||
int write_all_supers(struct btrfs_root *root);
|
||||
int write_ctree_super(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root);
|
||||
int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr);
|
||||
int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr,
|
||||
int super_recover);
|
||||
int btrfs_map_bh_to_logical(struct btrfs_root *root, struct extent_buffer *bh,
|
||||
u64 logical);
|
||||
struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
|
||||
|
@ -292,7 +292,7 @@ int btrfs_recover_superblocks(const char *dname,
|
||||
}
|
||||
init_recover_superblock(&recover);
|
||||
|
||||
ret = btrfs_scan_fs_devices(fd, dname, &recover.fs_devices, 0, 0);
|
||||
ret = btrfs_scan_fs_devices(fd, dname, &recover.fs_devices, 0, 0, 1);
|
||||
close(fd);
|
||||
if (ret) {
|
||||
ret = 1;
|
||||
|
11
utils.c
11
utils.c
@ -1163,7 +1163,7 @@ int check_mounted_where(int fd, const char *file, char *where, int size,
|
||||
|
||||
/* scan the initial device */
|
||||
ret = btrfs_scan_one_device(fd, file, &fs_devices_mnt,
|
||||
&total_devs, BTRFS_SUPER_INFO_OFFSET);
|
||||
&total_devs, BTRFS_SUPER_INFO_OFFSET, 0);
|
||||
is_btrfs = (ret >= 0);
|
||||
|
||||
/* scan other devices */
|
||||
@ -1325,7 +1325,7 @@ again:
|
||||
}
|
||||
ret = btrfs_scan_one_device(fd, fullpath, &tmp_devices,
|
||||
&num_devices,
|
||||
BTRFS_SUPER_INFO_OFFSET);
|
||||
BTRFS_SUPER_INFO_OFFSET, 0);
|
||||
if (ret == 0 && run_ioctl > 0) {
|
||||
btrfs_register_one_device(fullpath);
|
||||
}
|
||||
@ -1668,7 +1668,7 @@ scan_again:
|
||||
}
|
||||
ret = btrfs_scan_one_device(fd, fullpath, &tmp_devices,
|
||||
&num_devices,
|
||||
BTRFS_SUPER_INFO_OFFSET);
|
||||
BTRFS_SUPER_INFO_OFFSET, 0);
|
||||
if (ret == 0 && run_ioctl > 0) {
|
||||
btrfs_register_one_device(fullpath);
|
||||
}
|
||||
@ -1880,7 +1880,8 @@ int get_fs_info(char *path, struct btrfs_ioctl_fs_info_args *fi_args,
|
||||
fi_args->num_devices = 1;
|
||||
|
||||
disk_super = (struct btrfs_super_block *)buf;
|
||||
ret = btrfs_read_dev_super(fd, disk_super, BTRFS_SUPER_INFO_OFFSET);
|
||||
ret = btrfs_read_dev_super(fd, disk_super,
|
||||
BTRFS_SUPER_INFO_OFFSET, 0);
|
||||
if (ret < 0) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
@ -2229,7 +2230,7 @@ int btrfs_scan_lblkid(int update_kernel)
|
||||
continue;
|
||||
}
|
||||
ret = btrfs_scan_one_device(fd, path, &tmp_devices,
|
||||
&num_devices, BTRFS_SUPER_INFO_OFFSET);
|
||||
&num_devices, BTRFS_SUPER_INFO_OFFSET, 0);
|
||||
if (ret) {
|
||||
printf("ERROR: could not scan %s\n", path);
|
||||
close (fd);
|
||||
|
@ -233,7 +233,7 @@ fail:
|
||||
|
||||
int btrfs_scan_one_device(int fd, const char *path,
|
||||
struct btrfs_fs_devices **fs_devices_ret,
|
||||
u64 *total_devs, u64 super_offset)
|
||||
u64 *total_devs, u64 super_offset, int super_recover)
|
||||
{
|
||||
struct btrfs_super_block *disk_super;
|
||||
char *buf;
|
||||
@ -246,7 +246,7 @@ int btrfs_scan_one_device(int fd, const char *path,
|
||||
goto error;
|
||||
}
|
||||
disk_super = (struct btrfs_super_block *)buf;
|
||||
ret = btrfs_read_dev_super(fd, disk_super, super_offset);
|
||||
ret = btrfs_read_dev_super(fd, disk_super, super_offset, super_recover);
|
||||
if (ret < 0) {
|
||||
ret = -EIO;
|
||||
goto error_brelse;
|
||||
|
@ -179,7 +179,7 @@ int btrfs_update_device(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_device *device);
|
||||
int btrfs_scan_one_device(int fd, const char *path,
|
||||
struct btrfs_fs_devices **fs_devices_ret,
|
||||
u64 *total_devs, u64 super_offset);
|
||||
u64 *total_devs, u64 super_offset, int super_recover);
|
||||
int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len);
|
||||
struct list_head *btrfs_scanned_uuids(void);
|
||||
int btrfs_add_system_chunk(struct btrfs_trans_handle *trans,
|
||||
|
Loading…
Reference in New Issue
Block a user