From 26bf4f0a10dd192e4dc5494d2cf9398c666eaab6 Mon Sep 17 00:00:00 2001 From: Wang Shilong Date: Thu, 24 Apr 2014 18:51:10 +0800 Subject: [PATCH 15/42] Btrfs-progs: fsck: add ability to check reloc roots When encountering system crash or balance enospc errors, there maybe still some reloc roots left. The way we store reloc root is different from fs root: reloc root's root key(BTRFS_RELOC_TREE_OBJECTID, ROOT_ITEM, objectid) fs root's root key(objectid, ROOT_ITEM, -1) reloc data's root key(BTRFS_DATA_RELOC_TREE_OBJECTID, ROOT_ITEM, 0) So this patch use right key to search corresponding root node, and avoid using normal fs root cache for reloc roots. Signed-off-by: Wang Shilong Signed-off-by: David Sterba --- cmds-check.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/cmds-check.c b/cmds-check.c index 57d3f36eea1f..103efc5718ec 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -299,8 +299,22 @@ static struct inode_record *clone_inode_rec(struct inode_record *orig_rec) return rec; } -static void print_inode_error(int errors) +static void print_inode_error(struct btrfs_root *root, struct inode_record *rec) { + u64 root_objectid = root->root_key.objectid; + int errors = rec->errors; + + if (!errors) + return; + /* reloc root errors, we print its corresponding fs root objectid*/ + if (root_objectid == BTRFS_TREE_RELOC_OBJECTID) { + root_objectid = root->root_key.offset; + fprintf(stderr, "reloc"); + } + fprintf(stderr, "root %llu inode %llu errors %x", + (unsigned long long) root_objectid, + (unsigned long long) rec->ino, rec->errors); + if (errors & I_ERR_NO_INODE_ITEM) fprintf(stderr, ", no inode item"); if (errors & I_ERR_NO_ORPHAN_ITEM) @@ -1598,10 +1612,7 @@ static int check_inode_recs(struct btrfs_root *root, rec->errors |= I_ERR_NO_INODE_ITEM; if (rec->found_link != rec->nlink) rec->errors |= I_ERR_LINK_COUNT_WRONG; - fprintf(stderr, "root %llu inode %llu errors %x", - (unsigned long long) root->root_key.objectid, - (unsigned long long) rec->ino, rec->errors); - print_inode_error(rec->errors); + print_inode_error(root, rec); list_for_each_entry(backref, &rec->backrefs, list) { if (!backref->found_dir_item) backref->errors |= REF_ERR_NO_DIR_ITEM; @@ -2060,8 +2071,14 @@ static int check_fs_roots(struct btrfs_root *root, btrfs_item_key_to_cpu(leaf, &key, path.slots[0]); if (key.type == BTRFS_ROOT_ITEM_KEY && fs_root_objectid(key.objectid)) { - key.offset = (u64)-1; - tmp_root = btrfs_read_fs_root(root->fs_info, &key); + if (key.objectid == BTRFS_TREE_RELOC_OBJECTID) { + tmp_root = btrfs_read_fs_root_no_cache( + root->fs_info, &key); + } else { + key.offset = (u64)-1; + tmp_root = btrfs_read_fs_root( + root->fs_info, &key); + } if (IS_ERR(tmp_root)) { err = 1; goto next; @@ -2069,6 +2086,8 @@ static int check_fs_roots(struct btrfs_root *root, ret = check_fs_root(tmp_root, root_cache, &wc); if (ret) err = 1; + if (key.objectid == BTRFS_TREE_RELOC_OBJECTID) + btrfs_free_fs_root(tmp_root); } else if (key.type == BTRFS_ROOT_REF_KEY || key.type == BTRFS_ROOT_BACKREF_KEY) { process_root_ref(leaf, path.slots[0], &key, -- 1.9.0