Modify check_fs_first_inode to check firt_inode inode item and inode ref. Signed-off-by: Su Yue <suy.f...@cn.fujitsu.com> --- cmds-check.c | 57 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-)
diff --git a/cmds-check.c b/cmds-check.c index 246f4735..892a22ba 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -5169,42 +5169,68 @@ out: return err; } +/* + * check first root dir's inode_item, inde_ref + * + * returns 0 means no error + * returns >0 means error + * returns <0 means fatal error + */ static int check_fs_first_inode(struct btrfs_root *root, unsigned int ext_ref) { struct btrfs_path path; struct btrfs_key key; + struct btrfs_inode_item *ii; + u64 index = 0; + u32 mode; int err = 0; int ret; - key.objectid = BTRFS_FIRST_FREE_OBJECTID; - key.type = BTRFS_INODE_ITEM_KEY; - key.offset = 0; - /* For root being dropped, we don't need to check first inode */ if (btrfs_root_refs(&root->root_item) == 0 && btrfs_disk_key_objectid(&root->root_item.drop_progress) >= - key.objectid) + BTRFS_FIRST_FREE_OBJECTID) return 0; + /*search first inode item */ + key.objectid = BTRFS_FIRST_FREE_OBJECTID; + 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) + if (ret < 0) { goto out; - if (ret > 0) { - ret = 0; + } else if (ret > 0) { err |= INODE_ITEM_MISSING; - error("first inode item of root %llu is missing", - root->objectid); + } else { + ii = btrfs_item_ptr(path.nodes[0], path.slots[0], + struct btrfs_inode_item); + mode = btrfs_inode_mode(path.nodes[0], ii); + if (imode_to_type(mode) != BTRFS_FT_DIR) + err |= INODE_ITEM_MISMATCH; } + btrfs_release_path(&path); + + /* lookup first inode ref */ + key.offset = BTRFS_FIRST_FREE_OBJECTID; + key.type = BTRFS_INODE_REF_KEY; + + ret = find_inode_ref(root, &key, "..", strlen(".."), &index, ext_ref); + if (ret < 0) + goto out; + err |= ret; - err |= check_inode_item(root, &path, ext_ref); - err &= ~LAST_ITEM; - if (err && !ret) - ret = -EIO; out: btrfs_release_path(&path); - return ret; + if (err & (INODE_ITEM_MISSING | INODE_ITEM_MISMATCH)) + error("root dir INODE_ITEM is %s", + err & INODE_ITEM_MISMATCH ? "mismatch" : "missing"); + if (err & INODE_REF_MISSING) + error("root dir INODE_REF is missing"); + + return ret < 0 ? ret : err; } /* @@ -5232,6 +5258,7 @@ static int check_fs_root_v2(struct btrfs_root *root, unsigned int ext_ref) * we will just skip it forever. */ ret = check_fs_first_inode(root, ext_ref); + err |= !!ret; if (ret < 0) return ret; -- 2.11.1 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html