btrfs-progs: rescue/zero-log: Manually write all supers to handle extent tree error more gracefully

[BUG]
Even "btrfs rescue zero-log" only reset btrfs_super_block::log_root and
btrfs_super_block::log_root_level, we still use trasction to write all
super blocks for all devices.

This means we can't handle things like corrupted extent tree:

  checksum verify failed on 2172747776 found 000000B6 wanted 00000000
  checksum verify failed on 2172747776 found 000000B6 wanted 00000000
  bad tree block 2172747776, bytenr mismatch, want=2172747776, have=0
  WARNING: could not setup extent tree, skipping it
  Clearing log on /dev/nvme/btrfs, previous log_root 0, level 0
  ERROR: Corrupted fs, no valid METADATA block group found
  ERROR: attempt to start transaction over already running one

[CAUSE]
Because we have extra check in transaction code to ensure we have valid
METADATA block groups.

In fact we don't really need transaction at all.

[FIX]
Instead of commit transaction, we can just call write_all_supers()
manually, so we can still handle multi-device fs while avoid above
error.

Also, add OPEN_CTREE_NO_BLOCK_GROUPS open ctree flag to make it more
robust.

Link: https://lore.kernel.org/linux-btrfs/CAKbQEqG35D_=8raTFH75-yCYoqH2OvpPEmpj2dxgo+PTc=cfhA@mail.gmail.com/
Reported-by: Christian Pernegger <pernegger@gmail.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Qu Wenruo 2019-11-11 15:50:59 +08:00 committed by David Sterba
parent e731746a18
commit 9b01db7785
1 changed files with 7 additions and 6 deletions

View File

@ -165,7 +165,6 @@ static int cmd_rescue_zero_log(const struct cmd_struct *cmd,
int argc, char **argv)
{
struct btrfs_root *root;
struct btrfs_trans_handle *trans;
struct btrfs_super_block *sb;
char *devname;
int ret;
@ -187,7 +186,8 @@ static int cmd_rescue_zero_log(const struct cmd_struct *cmd,
goto out;
}
root = open_ctree(devname, 0, OPEN_CTREE_WRITES | OPEN_CTREE_PARTIAL);
root = open_ctree(devname, 0, OPEN_CTREE_WRITES | OPEN_CTREE_PARTIAL |
OPEN_CTREE_NO_BLOCK_GROUPS);
if (!root) {
error("could not open ctree");
return 1;
@ -198,13 +198,14 @@ static int cmd_rescue_zero_log(const struct cmd_struct *cmd,
devname,
(unsigned long long)btrfs_super_log_root(sb),
(unsigned)btrfs_super_log_root_level(sb));
trans = btrfs_start_transaction(root, 1);
BUG_ON(IS_ERR(trans));
btrfs_set_super_log_root(sb, 0);
btrfs_set_super_log_root_level(sb, 0);
btrfs_commit_transaction(trans, root);
ret = write_all_supers(root->fs_info);
if (ret < 0) {
errno = -ret;
error("failed to write dev supers: %m");
}
close_ctree(root);
out:
return !!ret;
}