From: Su Yue Date: Mon, 28 Aug 2017 05:54:21 +0000 (+0800) Subject: btrfs-progs: check: modify check_fs_first_inode() X-Git-Tag: upstream/4.16.1~348 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f32ca721257a78010a7ed8c6870a09c1274de1b2;p=platform%2Fupstream%2Fbtrfs-progs.git btrfs-progs: check: modify check_fs_first_inode() Modify check_fs_first_inode to check the inode ref in first inode. Which root dir inode differs from other inode is inode_ref points "..". So we just handle this special case and treat it as normal inode in continued check. Signed-off-by: Su Yue Signed-off-by: David Sterba --- diff --git a/cmds-check.c b/cmds-check.c index cbd0d7d..874a75a 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -5308,10 +5308,20 @@ out: return err; } +/* + * check first root dir's inode_item and inode_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; + u32 mode; int err = 0; int ret; @@ -5322,28 +5332,44 @@ static int check_fs_first_inode(struct btrfs_root *root, unsigned int ext_ref) /* 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; btrfs_init_path(&path); - ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret < 0) goto out; if (ret > 0) { 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; } - err |= check_inode_item(root, &path, ext_ref); - err &= ~LAST_ITEM; - if (err && !ret) - ret = -EIO; + /* lookup first inode ref */ + key.offset = BTRFS_FIRST_FREE_OBJECTID; + key.type = BTRFS_INODE_REF_KEY; + /* special index value */ + index = 0; + + ret = find_inode_ref(root, &key, "..", strlen(".."), &index, ext_ref); + if (ret < 0) + goto out; + err |= ret; + 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; } static struct tree_backref *find_tree_backref(struct extent_record *rec, @@ -5432,6 +5458,7 @@ static int check_fs_root_v2(struct btrfs_root *root, unsigned int ext_ref) ret = check_fs_first_inode(root, ext_ref); if (ret < 0) return ret; + err |= !!ret; memset(&nrefs, 0, sizeof(nrefs)); level = btrfs_header_level(root->node);