btrfs-progs: introduce OPEN_CTREE_ALLOW_TRANSID_MISMATCH flag
[BUG] There is a report that, btrfstune can even work while the fs has transid mismatch problems. $ btrfstune -f -u /dev/sdb1 Current fsid: b2b5ae8d-4c49-45f0-b42e-46fe7dcfcb07 New fsid: b2b5ae8d-4c49-45f0-b42e-46fe7dcfcb07 Set superblock flag CHANGING_FSID Change fsid in extents parent transid verify failed on 792854528 wanted 20103 found 20091 parent transid verify failed on 792854528 wanted 20103 found 20091 parent transid verify failed on 792854528 wanted 20103 found 20091 Ignoring transid failure parent transid verify failed on 792870912 wanted 20103 found 20091 parent transid verify failed on 792870912 wanted 20103 found 20091 parent transid verify failed on 792870912 wanted 20103 found 20091 Ignoring transid failure parent transid verify failed on 792887296 wanted 20103 found 20091 parent transid verify failed on 792887296 wanted 20103 found 20091 parent transid verify failed on 792887296 wanted 20103 found 20091 Ignoring transid failure ERROR: child eb corrupted: parent bytenr=38010880 item=69 parent level=1 child level=1 ERROR: failed to change UUID of metadata: -5 ERROR: btrfstune failed This leaves a corrupted fs even more corrupted, and due to the extra CHANGING_FSID flag, btrfs check will not even try to run on it: Opening filesystem to check... ERROR: Filesystem UUID change in progress ERROR: cannot open file system [CAUSE] Unlike kernel, btrfs-progs has a less strict check on transid mismatch. In read_tree_block() we will fall back to use the tree block even its transid mismatch if we can't find any better copy. However not all commands in btrfs-progs needs this feature, only btrfs-check (which may fix the problem) and btrfs-restore (it just tries to ignore any problems) really utilize this feature. [FIX] Introduce a new open ctree flag, OPEN_CTREE_ALLOW_TRANSID_MISMATCH, to be explicit about whether we really want to ignore transid error. Currently only btrfs-check and btrfs-restore will utilize this new flag. Also add btrfs-image to allow opening such fs with transid error. Link: https://www.reddit.com/r/btrfs/comments/pivpqk/failure_during_btrfstune_u/ Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
7d16785ab4
commit
60651ad9da
|
@ -10384,7 +10384,8 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
|
|||
int qgroup_report = 0;
|
||||
int qgroups_repaired = 0;
|
||||
int qgroup_verify_ret;
|
||||
unsigned ctree_flags = OPEN_CTREE_EXCLUSIVE;
|
||||
unsigned ctree_flags = OPEN_CTREE_EXCLUSIVE |
|
||||
OPEN_CTREE_ALLOW_TRANSID_MISMATCH;
|
||||
int force = 0;
|
||||
|
||||
while(1) {
|
||||
|
|
|
@ -1213,7 +1213,8 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location,
|
|||
ocf.filename = dev;
|
||||
ocf.sb_bytenr = bytenr;
|
||||
ocf.root_tree_bytenr = root_location;
|
||||
ocf.flags = OPEN_CTREE_PARTIAL | OPEN_CTREE_NO_BLOCK_GROUPS;
|
||||
ocf.flags = OPEN_CTREE_PARTIAL | OPEN_CTREE_NO_BLOCK_GROUPS |
|
||||
OPEN_CTREE_ALLOW_TRANSID_MISMATCH;
|
||||
fs_info = open_ctree_fs_info(&ocf);
|
||||
if (fs_info)
|
||||
break;
|
||||
|
|
11
image/main.c
11
image/main.c
|
@ -1004,7 +1004,7 @@ static int create_metadump(const char *input, FILE *out, int num_threads,
|
|||
int ret;
|
||||
int err = 0;
|
||||
|
||||
root = open_ctree(input, 0, 0);
|
||||
root = open_ctree(input, 0, OPEN_CTREE_ALLOW_TRANSID_MISMATCH);
|
||||
if (!root) {
|
||||
error("open ctree failed");
|
||||
return -EIO;
|
||||
|
@ -2781,7 +2781,8 @@ static int restore_metadump(const char *input, FILE *out, int old_restore,
|
|||
struct open_ctree_flags ocf = { 0 };
|
||||
|
||||
ocf.filename = target;
|
||||
ocf.flags = OPEN_CTREE_WRITES | OPEN_CTREE_RESTORE | OPEN_CTREE_PARTIAL;
|
||||
ocf.flags = OPEN_CTREE_WRITES | OPEN_CTREE_RESTORE |
|
||||
OPEN_CTREE_PARTIAL;
|
||||
info = open_ctree_fs_info(&ocf);
|
||||
if (!info) {
|
||||
error("open ctree failed");
|
||||
|
@ -2846,7 +2847,8 @@ static int restore_metadump(const char *input, FILE *out, int old_restore,
|
|||
root = open_ctree_fd(fileno(out), target, 0,
|
||||
OPEN_CTREE_PARTIAL |
|
||||
OPEN_CTREE_WRITES |
|
||||
OPEN_CTREE_NO_DEVICES);
|
||||
OPEN_CTREE_NO_DEVICES |
|
||||
OPEN_CTREE_ALLOW_TRANSID_MISMATCH);
|
||||
if (!root) {
|
||||
error("open ctree failed in %s", target);
|
||||
ret = -EIO;
|
||||
|
@ -2864,7 +2866,8 @@ static int restore_metadump(const char *input, FILE *out, int old_restore,
|
|||
u64 dev_size;
|
||||
|
||||
if (!info) {
|
||||
root = open_ctree_fd(fileno(out), target, 0, 0);
|
||||
root = open_ctree_fd(fileno(out), target, 0,
|
||||
OPEN_CTREE_ALLOW_TRANSID_MISMATCH);
|
||||
if (!root) {
|
||||
error("open ctree failed in %s", target);
|
||||
ret = -EIO;
|
||||
|
|
|
@ -1216,6 +1216,7 @@ struct btrfs_fs_info {
|
|||
unsigned int avoid_sys_chunk_alloc:1;
|
||||
unsigned int finalize_on_close:1;
|
||||
unsigned int hide_names:1;
|
||||
unsigned int allow_transid_mismatch:1;
|
||||
|
||||
int transaction_aborted;
|
||||
|
||||
|
|
|
@ -421,7 +421,7 @@ struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
|
|||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
if (num_copies == 1) {
|
||||
if (num_copies == 1 && fs_info->allow_transid_mismatch) {
|
||||
ignore = 1;
|
||||
continue;
|
||||
}
|
||||
|
@ -431,6 +431,10 @@ struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
|
|||
}
|
||||
mirror_num++;
|
||||
if (mirror_num > num_copies) {
|
||||
if (!fs_info->allow_transid_mismatch) {
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
if (candidate_mirror > 0)
|
||||
mirror_num = candidate_mirror;
|
||||
else
|
||||
|
@ -1231,6 +1235,8 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, struct open_ctree_flags *oc
|
|||
fs_info->ignore_chunk_tree_error = 1;
|
||||
if (flags & OPEN_CTREE_HIDE_NAMES)
|
||||
fs_info->hide_names = 1;
|
||||
if (flags & OPEN_CTREE_ALLOW_TRANSID_MISMATCH)
|
||||
fs_info->allow_transid_mismatch = 1;
|
||||
|
||||
if ((flags & OPEN_CTREE_RECOVER_SUPER)
|
||||
&& (flags & OPEN_CTREE_TEMPORARY_SUPER)) {
|
||||
|
@ -1988,7 +1994,8 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
|
|||
return ret;
|
||||
|
||||
ret = verify_parent_transid(&buf->fs_info->extent_cache, buf,
|
||||
parent_transid, 1);
|
||||
parent_transid,
|
||||
buf->fs_info->allow_transid_mismatch);
|
||||
return !ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,12 @@ enum btrfs_open_ctree_flags {
|
|||
|
||||
/* For print-tree, print HIDDEN instead of filenames/xattrs/refs */
|
||||
OPEN_CTREE_HIDE_NAMES = (1U << 14),
|
||||
|
||||
/*
|
||||
* Allow certain commands like check/restore to ignore transid
|
||||
* mismatch.
|
||||
*/
|
||||
OPEN_CTREE_ALLOW_TRANSID_MISMATCH = (1U << 15),
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue