diff options
author | David Sterba <dsterba@suse.com> | 2016-09-05 12:02:31 +0200 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2016-09-05 12:20:24 +0200 |
commit | 50882c447d6a5abd2b11134d6b4576f9f4f02475 (patch) | |
tree | ca1de148184bdd560b7d4b496216e269a4e77f5f | |
parent | b1c0235e11c7bae27e7cf86f256c3cb650e63041 (diff) |
Revert "btrfs-progs: check: supplement extent backref list with rbtree"
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>
-rw-r--r-- | cmds-check.c | 193 |
1 files changed, 48 insertions, 145 deletions
diff --git a/cmds-check.c b/cmds-check.c index 5a3efef9..a453696e 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -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; |