summaryrefslogtreecommitdiff
path: root/cmds-check.c
diff options
context:
space:
mode:
authorLu Fengqi <lufq.fnst@cn.fujitsu.com>2016-07-26 11:18:40 +0800
committerDavid Sterba <dsterba@suse.com>2016-12-14 15:06:33 +0100
commit262425b6504af0b643c52c0dbfc0f26f79d7fe5b (patch)
tree39b61185e0327d25e728f74fb95a707f054b0f42 /cmds-check.c
parentb1d1f627ce53e1deeb7068df8861a0d0425044b0 (diff)
btrfs-progs: check: introduce function to check fs root
Introduce a new function check_fs_root_v2() to check fs root, and call check_inode_item to check the items in the tree. Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com> Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'cmds-check.c')
-rw-r--r--cmds-check.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/cmds-check.c b/cmds-check.c
index 6937c53f..b965f2e4 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -3840,6 +3840,7 @@ out:
#define NBYTES_ERROR (1<<11) /* INODE_ITEM nbytes count error */
#define ISIZE_ERROR (1<<12) /* INODE_ITEM size count error */
#define ORPHAN_ITEM (1<<13) /* INODE_ITEM no reference */
+#define NO_INODE_ITEM (1<<14) /* no inode_item */
#define LAST_ITEM (1<<15) /* Complete this tree traversal */
/*
@@ -4658,6 +4659,81 @@ out:
return err;
}
+/*
+ * Iterate all item on the tree and call check_inode_item() to check.
+ *
+ * @root: the root of the tree to be checked.
+ * @ext_ref: the EXTENDED_IREF feature
+ *
+ * Return 0 if no error found.
+ * Return <0 for error.
+ * All internal error bitmap will be converted to -EIO, to avoid
+ * mixing negative and postive return value.
+ */
+static int check_fs_root_v2(struct btrfs_root *root, unsigned int ext_ref)
+{
+ struct btrfs_path *path;
+ struct btrfs_key key;
+ u64 inode_id;
+ int ret, err = 0;
+
+ path = btrfs_alloc_path();
+ if (!path)
+ return -ENOMEM;
+
+ key.objectid = 0;
+ key.type = 0;
+ key.offset = 0;
+
+ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+ if (ret < 0)
+ goto out;
+
+ while (1) {
+ btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
+
+ /*
+ * All check must start with inode item, skip if not
+ */
+ if (key.type == BTRFS_INODE_ITEM_KEY) {
+ ret = check_inode_item(root, path, ext_ref);
+ err |= ret;
+ if (err & LAST_ITEM)
+ goto out;
+ continue;
+ }
+ error("root %llu ITEM[%llu %u %llu] isn't INODE_ITEM, skip to next inode",
+ root->objectid, key.objectid, key.type,
+ key.offset);
+
+ err |= NO_INODE_ITEM;
+ inode_id = key.objectid;
+
+ /*
+ * skip to next inode
+ * TODO: Maybe search_slot() will be faster?
+ */
+ do {
+ ret = btrfs_next_item(root, path);
+ if (ret > 0) {
+ goto out;
+ } else if (ret < 0) {
+ err = ret;
+ goto out;
+ }
+ btrfs_item_key_to_cpu(path->nodes[0], &key,
+ path->slots[0]);
+ } while (inode_id == key.objectid);
+ }
+
+out:
+ err &= ~LAST_ITEM;
+ if (err && !ret)
+ ret = -EIO;
+ btrfs_free_path(path);
+ return ret;
+}
+
static int all_backpointers_checked(struct extent_record *rec, int print_errs)
{
struct list_head *cur = rec->backrefs.next;