Revert "btrfs-progs: check: supplement extent backref list with rbtree"
authorDavid Sterba <dsterba@suse.com>
Mon, 5 Sep 2016 10:02:31 +0000 (12:02 +0200)
committerDavid Sterba <dsterba@suse.com>
Mon, 5 Sep 2016 10:20:24 +0000 (12:20 +0200)
This reverts commit 31d8235410985e0b64487354c9ba67d40c4bdfe3.

False report of backref mismatches, lots of messages similar to:

Incorrect local backref count on 12713984 root 5 owner 257 offset 12845056 found 1 wanted 0 back 0x7b3ed0
backpointer mismatch on [12713984 131072]

Repairing will make things worse. A fix has been proposed, but is not
finalized so we go with a revert.

Reported-by: Chris Murphy <bugzilla@colorremedies.com>
References: https://bugzilla.kernel.org/show_bug.cgi?id=155791
Signed-off-by: David Sterba <dsterba@suse.com>
cmds-check.c

index 5a3efef9440666f5613f67d6c8fd5eecdde67c20..a453696e638730eeffc10db7ee525354d1f7abaf 100644 (file)
@@ -85,7 +85,6 @@ static enum btrfs_check_mode check_mode = CHECK_MODE_DEFAULT;
 
 struct extent_backref {
        struct list_head list;
-       struct rb_node node;
        unsigned int is_data:1;
        unsigned int found_extent_tree:1;
        unsigned int full_backref:1;
@@ -98,11 +97,6 @@ static inline struct extent_backref* to_extent_backref(struct list_head *entry)
        return list_entry(entry, struct extent_backref, list);
 }
 
-static inline struct extent_backref* rb_node_to_extent_backref(struct rb_node *node)
-{
-       return rb_entry(node, struct extent_backref, node);
-}
-
 struct data_backref {
        struct extent_backref node;
        union {
@@ -123,56 +117,6 @@ static inline struct data_backref* to_data_backref(struct extent_backref *back)
        return container_of(back, struct data_backref, node);
 }
 
-static int compare_data_backref(struct rb_node *node1, struct rb_node *node2)
-{
-       struct extent_backref *ext1 = rb_node_to_extent_backref(node1);
-       struct extent_backref *ext2 = rb_node_to_extent_backref(node2);
-       struct data_backref *back1 = to_data_backref(ext1);
-       struct data_backref *back2 = to_data_backref(ext2);
-
-       WARN_ON(!ext1->is_data);
-       WARN_ON(!ext2->is_data);
-
-       /* parent and root are a union, so this covers both */
-       if (back1->parent > back2->parent)
-               return 1;
-       if (back1->parent < back2->parent)
-               return -1;
-
-       /* This is a full backref and the parents match. */
-       if (back1->node.full_backref)
-               return 0;
-
-       if (back1->owner > back2->owner)
-               return 1;
-       if (back1->owner < back2->owner)
-               return -1;
-
-       if (back1->offset > back2->offset)
-               return 1;
-       if (back1->offset < back2->offset)
-               return -1;
-
-       if (back1->bytes > back2->bytes)
-               return 1;
-       if (back1->bytes < back2->bytes)
-               return -1;
-
-       if (back1->found_ref && back2->found_ref) {
-               if (back1->disk_bytenr > back2->disk_bytenr)
-                       return 1;
-               if (back1->disk_bytenr < back2->disk_bytenr)
-                       return -1;
-
-               if (back1->found_ref > back2->found_ref)
-                       return 1;
-               if (back1->found_ref < back2->found_ref)
-                       return -1;
-       }
-
-       return 0;
-}
-
 /*
  * Much like data_backref, just removed the undetermined members
  * and change it to use list_head.
@@ -201,54 +145,12 @@ static inline struct tree_backref* to_tree_backref(struct extent_backref *back)
        return container_of(back, struct tree_backref, node);
 }
 
-static int compare_tree_backref(struct rb_node *node1, struct rb_node *node2)
-{
-       struct extent_backref *ext1 = rb_node_to_extent_backref(node1);
-       struct extent_backref *ext2 = rb_node_to_extent_backref(node2);
-       struct tree_backref *back1 = to_tree_backref(ext1);
-       struct tree_backref *back2 = to_tree_backref(ext2);
-
-       WARN_ON(ext1->is_data);
-       WARN_ON(ext2->is_data);
-
-       /* parent and root are a union, so this covers both */
-       if (back1->parent > back2->parent)
-               return 1;
-       if (back1->parent < back2->parent)
-               return -1;
-
-       return 0;
-}
-
-static int compare_extent_backref(struct rb_node *node1, struct rb_node *node2)
-{
-       struct extent_backref *ext1 = rb_node_to_extent_backref(node1);
-       struct extent_backref *ext2 = rb_node_to_extent_backref(node2);
-
-       if (ext1->is_data > ext2->is_data)
-               return 1;
-
-       if (ext1->is_data < ext2->is_data)
-               return -1;
-
-       if (ext1->full_backref > ext2->full_backref)
-               return 1;
-       if (ext1->full_backref < ext2->full_backref)
-               return -1;
-
-       if (ext1->is_data)
-               return compare_data_backref(node1, node2);
-       else
-               return compare_tree_backref(node1, node2);
-}
-
 /* Explicit initialization for extent_record::flag_block_full_backref */
 enum { FLAG_UNSET = 2 };
 
 struct extent_record {
        struct list_head backrefs;
        struct list_head dups;
-       struct rb_root backref_tree;
        struct list_head list;
        struct cache_extent cache;
        struct btrfs_disk_key parent_key;
@@ -4538,31 +4440,32 @@ static int check_block(struct btrfs_root *root,
        return ret;
 }
 
-
 static struct tree_backref *find_tree_backref(struct extent_record *rec,
                                                u64 parent, u64 root)
 {
-       struct rb_node *node;
-       struct tree_backref *back = NULL;
-       struct tree_backref match = {
-               .node = {
-                       .is_data = 0,
-               },
-       };
+       struct list_head *cur = rec->backrefs.next;
+       struct extent_backref *node;
+       struct tree_backref *back;
 
-       if (parent) {
-               match.parent = parent;
-               match.node.full_backref = 1;
-       } else {
-               match.root = root;
+       while(cur != &rec->backrefs) {
+               node = to_extent_backref(cur);
+               cur = cur->next;
+               if (node->is_data)
+                       continue;
+               back = to_tree_backref(node);
+               if (parent > 0) {
+                       if (!node->full_backref)
+                               continue;
+                       if (parent == back->parent)
+                               return back;
+               } else {
+                       if (node->full_backref)
+                               continue;
+                       if (back->root == root)
+                               return back;
+               }
        }
-
-       node = rb_search(&rec->backref_tree, &match.node.node,
-                        (rb_compare_keys)compare_extent_backref, NULL);
-       if (node)
-               back = to_tree_backref(rb_node_to_extent_backref(node));
-
-       return back;
+       return NULL;
 }
 
 static struct tree_backref *alloc_tree_backref(struct extent_record *rec,
@@ -4581,7 +4484,6 @@ static struct tree_backref *alloc_tree_backref(struct extent_record *rec,
                ref->node.full_backref = 0;
        }
        list_add_tail(&ref->node.list, &rec->backrefs);
-       rb_insert(&rec->backref_tree, &ref->node.node, compare_extent_backref);
 
        return ref;
 }
@@ -4592,32 +4494,35 @@ static struct data_backref *find_data_backref(struct extent_record *rec,
                                                int found_ref,
                                                u64 disk_bytenr, u64 bytes)
 {
-       struct rb_node *node;
-       struct data_backref *back = NULL;
-       struct data_backref match = {
-               .node = {
-                       .is_data = 1,
-               },
-               .owner = owner,
-               .offset = offset,
-               .bytes = bytes,
-               .found_ref = found_ref,
-               .disk_bytenr = disk_bytenr,
-       };
+       struct list_head *cur = rec->backrefs.next;
+       struct extent_backref *node;
+       struct data_backref *back;
 
-       if (parent) {
-               match.parent = parent;
-               match.node.full_backref = 1;
-       } else {
-               match.root = root;
+       while(cur != &rec->backrefs) {
+               node = to_extent_backref(cur);
+               cur = cur->next;
+               if (!node->is_data)
+                       continue;
+               back = to_data_backref(node);
+               if (parent > 0) {
+                       if (!node->full_backref)
+                               continue;
+                       if (parent == back->parent)
+                               return back;
+               } else {
+                       if (node->full_backref)
+                               continue;
+                       if (back->root == root && back->owner == owner &&
+                           back->offset == offset) {
+                               if (found_ref && node->found_ref &&
+                                   (back->bytes != bytes ||
+                                   back->disk_bytenr != disk_bytenr))
+                                       continue;
+                               return back;
+                       }
+               }
        }
-
-       node = rb_search(&rec->backref_tree, &match.node.node,
-                        (rb_compare_keys)compare_extent_backref, NULL);
-       if (node)
-               back = to_data_backref(rb_node_to_extent_backref(node));
-
-       return back;
+       return NULL;
 }
 
 static struct data_backref *alloc_data_backref(struct extent_record *rec,
@@ -4647,7 +4552,6 @@ static struct data_backref *alloc_data_backref(struct extent_record *rec,
        ref->found_ref = 0;
        ref->num_refs = 0;
        list_add_tail(&ref->node.list, &rec->backrefs);
-       rb_insert(&rec->backref_tree, &ref->node.node, compare_extent_backref);
        if (max_size > rec->max_size)
                rec->max_size = max_size;
        return ref;
@@ -4735,7 +4639,6 @@ static int add_extent_rec_nolookup(struct cache_tree *extent_cache,
        INIT_LIST_HEAD(&rec->backrefs);
        INIT_LIST_HEAD(&rec->dups);
        INIT_LIST_HEAD(&rec->list);
-       rec->backref_tree = RB_ROOT;
        memcpy(&rec->parent_key, &tmpl->parent_key, sizeof(tmpl->parent_key));
        rec->cache.start = tmpl->start;
        rec->cache.size = tmpl->nr;