btrfs-progs: check/lowmem: Repair bad imode early
For lowmem mode, if we hit a bad inode mode, normally it is reported when we checking the DIR_INDEX/DIR_ITEM of the parent inode. If we didn't repair at that time, the error will be recorded even if we fixed it later. So this patch will check for INODE_ITEM_MISMATCH error type, and if it's really caused by invalid imode, repair it and clear the error. Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
7f8383b7a6
commit
69eac9de0c
|
@ -1550,6 +1550,35 @@ static int lowmem_delete_corrupted_dir_item(struct btrfs_root *root,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int try_repair_imode(struct btrfs_root *root, u64 ino)
|
||||
{
|
||||
struct btrfs_inode_item *iitem;
|
||||
struct btrfs_path path;
|
||||
struct btrfs_key key;
|
||||
int ret;
|
||||
|
||||
key.objectid = ino;
|
||||
key.type = BTRFS_INODE_ITEM_KEY;
|
||||
key.offset = 0;
|
||||
btrfs_init_path(&path);
|
||||
|
||||
ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
|
||||
if (ret > 0)
|
||||
ret = -ENOENT;
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
iitem = btrfs_item_ptr(path.nodes[0], path.slots[0],
|
||||
struct btrfs_inode_item);
|
||||
if (!is_valid_imode(btrfs_inode_mode(path.nodes[0], iitem))) {
|
||||
ret = repair_imode_common(root, &path);
|
||||
} else {
|
||||
ret = -ENOTTY;
|
||||
}
|
||||
out:
|
||||
btrfs_release_path(&path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call repair_inode_item_missing and repair_ternary_lowmem to repair
|
||||
*
|
||||
|
@ -1574,6 +1603,16 @@ static int repair_dir_item(struct btrfs_root *root, struct btrfs_key *di_key,
|
|||
err &= ~(INODE_ITEM_MISMATCH | INODE_ITEM_MISSING);
|
||||
}
|
||||
|
||||
if (err & INODE_ITEM_MISMATCH) {
|
||||
/*
|
||||
* INODE_ITEM mismatch can be caused by bad imode, so check if
|
||||
* it's a bad imode, then repair if possible.
|
||||
*/
|
||||
ret = try_repair_imode(root, ino);
|
||||
if (!ret)
|
||||
err &= ~INODE_ITEM_MISMATCH;
|
||||
}
|
||||
|
||||
if (err & ~(INODE_ITEM_MISMATCH | INODE_ITEM_MISSING)) {
|
||||
ret = repair_ternary_lowmem(root, dirid, ino, index, namebuf,
|
||||
name_len, filetype, err);
|
||||
|
|
Loading…
Reference in New Issue