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;
|
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
|
* 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);
|
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)) {
|
if (err & ~(INODE_ITEM_MISMATCH | INODE_ITEM_MISSING)) {
|
||||||
ret = repair_ternary_lowmem(root, dirid, ino, index, namebuf,
|
ret = repair_ternary_lowmem(root, dirid, ino, index, namebuf,
|
||||||
name_len, filetype, err);
|
name_len, filetype, err);
|
||||||
|
|
Loading…
Reference in New Issue