diff options
author | Su Yue <suy.fnst@cn.fujitsu.com> | 2017-08-28 16:08:55 +0800 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-10-16 20:33:00 +0200 |
commit | 839b3c5214c7d0fb3fa87969ab0b9ece9e6baa77 (patch) | |
tree | 0ec7d575d79226728d4ebd7981235d9a9226c017 | |
parent | cac2b0390de8cd4f9a79ddf7e9a6a6e9522cef56 (diff) |
btrfs-progs: check: introduce repair_fs_first_inode()
Introduce 'repair_fs_first_inode' to repair first inode errors
(ref missing and inode item missing).
Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r-- | cmds-check.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/cmds-check.c b/cmds-check.c index 17ce0bb1..ebb542c6 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -5535,6 +5535,70 @@ out: } /* + * Insert the missing inode item and inode ref. + * + * Normal INODE_ITEM_MISSING and INODE_REF_MISSING are handled in backref * dir. + * Root dir should be handled specially because root dir is the root of fs. + * + * returns err (>0 or 0) after repair + */ +static int repair_fs_first_inode(struct btrfs_root *root, int err) +{ + struct btrfs_trans_handle *trans; + struct btrfs_key key; + struct btrfs_path path; + int filetype = BTRFS_FT_DIR; + int ret = 0; + + btrfs_init_path(&path); + + if (err & INODE_REF_MISSING) { + key.objectid = BTRFS_FIRST_FREE_OBJECTID; + key.type = BTRFS_INODE_REF_KEY; + key.offset = BTRFS_FIRST_FREE_OBJECTID; + + trans = btrfs_start_transaction(root, 1); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + goto out; + } + + btrfs_release_path(&path); + ret = btrfs_search_slot(trans, root, &key, &path, 1, 1); + if (ret) + goto trans_fail; + + ret = btrfs_insert_inode_ref(trans, root, "..", 2, + BTRFS_FIRST_FREE_OBJECTID, + BTRFS_FIRST_FREE_OBJECTID, 0); + if (ret) + goto trans_fail; + + printf("Add INODE_REF[%llu %llu] name %s\n", + BTRFS_FIRST_FREE_OBJECTID, BTRFS_FIRST_FREE_OBJECTID, + ".."); + err &= ~INODE_REF_MISSING; +trans_fail: + if (ret) + error("fail to insert first inode's ref"); + btrfs_commit_transaction(trans, root); + } + + if (err & INODE_ITEM_MISSING) { + ret = repair_inode_item_missing(root, + BTRFS_FIRST_FREE_OBJECTID, filetype); + if (ret) + goto out; + err &= ~INODE_ITEM_MISSING; + } +out: + if (ret) + error("fail to repair first inode"); + btrfs_release_path(&path); + return err; +} + +/* * check first root dir's inode_item and inode_ref * * returns 0 means no error @@ -5589,6 +5653,10 @@ static int check_fs_first_inode(struct btrfs_root *root, unsigned int ext_ref) out: btrfs_release_path(&path); + + if (err && repair) + err = repair_fs_first_inode(root, err); + if (err & (INODE_ITEM_MISSING | INODE_ITEM_MISMATCH)) error("root dir INODE_ITEM is %s", err & INODE_ITEM_MISMATCH ? "mismatch" : "missing"); |