>From accf27e37d7787b2f66512c85e5136a4935315b6 Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Thu, 18 Oct 2012 14:14:57 +0800 Subject: [PATCH 2/3] Btrfs: debug part 1 Signed-off-by: Liu Bo --- fs/btrfs/inode.c | 87 ++++++++++++++++++++++++----------------------------- 1 files changed, 39 insertions(+), 48 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index cef281a..434ce43 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1893,7 +1893,6 @@ static int backref_comp(struct sa_defrag_extent_backref *b1, else if (b1->file_pos > b2->file_pos) return 1; - WARN_ON(1); return 0; } @@ -1912,10 +1911,8 @@ static void backref_insert(struct rb_root *root, ret = backref_comp(backref, entry); if (ret < 0) p = &(*p)->rb_left; - else if (ret > 0) - p = &(*p)->rb_right; else - BUG_ON(1); + p = &(*p)->rb_right; } rb_link_node(&backref->node, parent, p); @@ -1996,7 +1993,10 @@ static noinline int record_one_backref(u64 inum, u64 offset, u64 root_id, btrfs_item_key_to_cpu(leaf, &key, slot); - if (key.objectid != inum || key.type != BTRFS_EXTENT_DATA_KEY) + if (key.objectid > inum) + goto out; + + if (key.objectid < inum || key.type != BTRFS_EXTENT_DATA_KEY) continue; extent = btrfs_item_ptr(leaf, slot, @@ -2005,20 +2005,18 @@ static noinline int record_one_backref(u64 inum, u64 offset, u64 root_id, if (btrfs_file_extent_disk_bytenr(leaf, extent) != old->bytenr) continue; - if (key.offset - btrfs_file_extent_offset(leaf, extent) != - offset) + extent_offset = btrfs_file_extent_offset(leaf, extent); + if (key.offset - extent_offset != offset) + continue; + + num_bytes = btrfs_file_extent_num_bytes(leaf, extent); + if (extent_offset >= old->extent_offset + old->offset + old->len || + extent_offset + num_bytes <= old->extent_offset + old->offset) continue; break; } - extent_offset = btrfs_file_extent_offset(leaf, extent); - num_bytes = btrfs_file_extent_num_bytes(leaf, extent); - - if (extent_offset >= old->extent_offset + old->offset + old->len || - extent_offset + num_bytes < old->extent_offset + old->offset) - goto out; - backref = kmalloc(sizeof(*backref), GFP_NOFS); if (!backref) { ret = -ENOENT; @@ -2053,7 +2051,7 @@ static noinline bool record_extent_backrefs(struct btrfs_path *path, ret = iterate_inodes_from_logical(old->bytenr, fs_info, path, record_one_backref, old); - WARN_ON(ret < 0); + BUG_ON(ret < 0 && ret != -ENOENT); /* no backref to be processed for this extent */ if (!old->count) { @@ -2092,11 +2090,12 @@ static noinline int relink_extent_backref(struct btrfs_path *path, u64 hint_byte; u64 start; u64 len; + u64 lock_start; + u64 lock_end; bool merge = false; if (prev && prev->root_id == backref->root_id && prev->inum == backref->inum && - prev->extent_offset == backref->extent_offset && prev->file_pos + prev->num_bytes == backref->file_pos) merge = true; @@ -2123,26 +2122,15 @@ static noinline int relink_extent_backref(struct btrfs_path *path, return 0; } - lock_extent_bits(&BTRFS_I(inode)->io_tree, backref->file_pos, - backref->file_pos + backref->num_bytes, 0, &cached); - - ordered = btrfs_lookup_first_ordered_extent(inode, - backref->file_pos + - backref->num_bytes); - if (ordered) { - btrfs_put_ordered_extent(ordered); - goto out_unlock; - } - /* * 1 for drop_extents * 1 for merge clause's search_slot * 1 for insert items */ - trans = btrfs_start_transaction(root, 3); + trans = btrfs_join_transaction(root); if (IS_ERR(trans)) { ret = PTR_ERR(trans); - goto out_unlock; + goto out_free_path; } key.objectid = backref->inum; @@ -2175,10 +2163,21 @@ static noinline int relink_extent_backref(struct btrfs_path *path, old->extent_offset + old->offset + old->len); len -= max(backref->extent_offset, old->extent_offset + old->offset); + lock_start = backref->file_pos; + lock_end = backref->file_pos + backref->num_bytes - 1; + lock_extent_bits(&BTRFS_I(inode)->io_tree, lock_start, lock_end, 0, &cached); + + ordered = btrfs_lookup_first_ordered_extent(inode, lock_end); + if (ordered) { + btrfs_put_ordered_extent(ordered); + goto out_unlock; + } + + ret = btrfs_drop_extents(trans, inode, start, start + len, &hint_byte, 1); if (ret) - goto out_free_path; + goto out_unlock; again: key.objectid = btrfs_ino(inode); key.type = BTRFS_EXTENT_DATA_KEY; @@ -2191,7 +2190,7 @@ again: ret = btrfs_search_slot(trans, root, &key, path, 1, 1); if (ret < 0) - goto out_free_path; + goto out_unlock; path->slots[0]--; leaf = path->nodes[0]; @@ -2213,7 +2212,7 @@ again: inode_add_bytes(inode, len); ret = 1; - goto out_free_path; + goto out_unlock; } else { merge = false; btrfs_release_path(path); @@ -2225,7 +2224,7 @@ again: sizeof(*extent)); if (ret) { btrfs_abort_transaction(trans, root, ret); - goto out_free_path; + goto out_unlock; } leaf = path->nodes[0]; @@ -2248,20 +2247,19 @@ again: ret = btrfs_inc_extent_ref(trans, root, new->bytenr, new->disk_len, 0, backref->root_id, backref->inum, - start, 0); + new->file_pos, 0); /* start - extent_offset */ if (ret) { btrfs_abort_transaction(trans, root, ret); - goto out_free_path; + goto out_unlock; } ret = 1; +out_unlock: + unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start, lock_end, &cached, GFP_NOFS); out_free_path: btrfs_release_path(path); - btrfs_end_transaction(trans, root); -out_unlock: - unlock_extent_cached(&BTRFS_I(inode)->io_tree, backref->file_pos, - backref->file_pos + backref->num_bytes, - &cached, GFP_NOFS); + if (trans) + btrfs_end_transaction(trans, root); iput(inode); return ret; } @@ -2275,7 +2273,6 @@ static void relink_file_extents(struct new_sa_defrag_extent *new) struct inode *inode; struct btrfs_root *root; struct rb_node *node; - struct extent_state *cached = NULL; int ret; inode = new->inode; @@ -2291,9 +2288,6 @@ static void relink_file_extents(struct new_sa_defrag_extent *new) } btrfs_release_path(path); - lock_extent_bits(&BTRFS_I(inode)->io_tree, new->file_pos, - new->file_pos + new->len, 0, &cached); - while (1) { node = rb_first(&new->root); if (!node) @@ -2313,12 +2307,8 @@ static void relink_file_extents(struct new_sa_defrag_extent *new) prev = NULL; cond_resched(); } - kfree(prev); - unlock_extent_cached(&BTRFS_I(inode)->io_tree, new->file_pos, - new->file_pos + new->len, &cached, GFP_NOFS); - btrfs_free_path(path); list_for_each_entry_safe(old, tmp, &new->head, list) { @@ -2414,6 +2404,7 @@ record_old_file_extents(struct inode *inode, end = min(new->file_pos + new->len, key.offset + num_bytes); old->bytenr = btrfs_file_extent_disk_bytenr(l, extent); + BUG_ON(!old->bytenr); old->extent_offset = btrfs_file_extent_offset(l, extent); old->offset = offset - key.offset; old->len = end - offset; -- 1.7.7.6