diff -r cf052b443059 ctree.h --- a/ctree.h Sun Jul 27 06:39:00 2008 -0400 +++ b/ctree.h Mon Jul 28 11:03:41 2008 -0400 @@ -594,7 +594,6 @@ struct btrfs_fs_info { spinlock_t ref_cache_lock; u64 total_ref_cache_size; - u64 running_ref_cache_size; u64 avail_data_alloc_bits; u64 avail_metadata_alloc_bits; @@ -606,10 +605,17 @@ struct btrfs_fs_info { void *bdev_holder; }; +struct btrfs_leaf_ref_tree { + struct rb_root root; + struct btrfs_leaf_ref *last; + spinlock_t lock; +}; + /* * in ram representation of the tree. extent_root is used for all allocations * and for the extent tree extent_root root. */ +struct dirty_root; struct btrfs_root { struct extent_buffer *node; @@ -618,6 +624,8 @@ struct btrfs_root { struct extent_buffer *commit_root; struct btrfs_leaf_ref_tree *ref_tree; + struct btrfs_leaf_ref_tree ref_tree_struct; + struct dirty_root *dirty_root; struct btrfs_root_item root_item; struct btrfs_key root_key; diff -r cf052b443059 disk-io.c --- a/disk-io.c Sun Jul 27 06:39:00 2008 -0400 +++ b/disk-io.c Mon Jul 28 11:03:41 2008 -0400 @@ -40,6 +40,7 @@ #include "print-tree.h" #include "async-thread.h" #include "locking.h" +#include "ref-cache.h" #if 0 static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf) @@ -737,6 +738,10 @@ static int __setup_root(u32 nodesize, u3 spin_lock_init(&root->node_lock); spin_lock_init(&root->orphan_lock); mutex_init(&root->objectid_mutex); + + btrfs_leaf_ref_tree_init(&root->ref_tree_struct); + root->ref_tree = &root->ref_tree_struct; + memset(&root->root_key, 0, sizeof(root->root_key)); memset(&root->root_item, 0, sizeof(root->root_item)); memset(&root->defrag_progress, 0, sizeof(root->defrag_progress)); @@ -1176,9 +1181,6 @@ static int transaction_kthread(void *arg goto sleep; } - printk("btrfs: running reference cache size %Lu\n", - root->fs_info->running_ref_cache_size); - now = get_seconds(); if (now < cur->start_time || now - cur->start_time < 30) { mutex_unlock(&root->fs_info->trans_mutex); diff -r cf052b443059 extent-tree.c --- a/extent-tree.c Sun Jul 27 06:39:00 2008 -0400 +++ b/extent-tree.c Mon Jul 28 11:03:41 2008 -0400 @@ -2468,11 +2468,11 @@ static int noinline walk_down_tree(struc BUG_ON(ret); continue; } - + if (*level == 1) { struct btrfs_key key; btrfs_node_key_to_cpu(cur, &key, path->slots[*level]); - ref = btrfs_lookup_leaf_ref(root, &key); + ref = btrfs_lookup_leaf_ref(root, ptr_gen, &key); if (ref) { ret = drop_leaf_ref(trans, root, ref); BUG_ON(ret); @@ -2481,8 +2481,8 @@ static int noinline walk_down_tree(struc *level = 0; break; } +printk("extent cache miss bytenr %Lu gen %Lu\n", bytenr, ptr_gen); } - next = btrfs_find_tree_block(root, bytenr, blocksize); if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) { free_extent_buffer(next); diff -r cf052b443059 ref-cache.c --- a/ref-cache.c Sun Jul 27 06:39:00 2008 -0400 +++ b/ref-cache.c Mon Jul 28 11:03:42 2008 -0400 @@ -44,8 +44,13 @@ void btrfs_free_leaf_ref(struct btrfs_le } } -static int comp_keys(struct btrfs_key *k1, struct btrfs_key *k2) +static int comp_keys(u64 gen1, u64 gen2, struct btrfs_key *k1, + struct btrfs_key *k2) { + if (gen1 > gen2) + return 1; + if (gen1 < gen2) + return -1; if (k1->objectid > k2->objectid) return 1; if (k1->objectid < k2->objectid) @@ -61,7 +66,8 @@ static int comp_keys(struct btrfs_key *k return 0; } -static struct rb_node *tree_insert(struct rb_root *root, struct btrfs_key *key, +static struct rb_node *tree_insert(struct rb_root *root, u64 gen, + struct btrfs_key *key, struct rb_node *node) { struct rb_node ** p = &root->rb_node; @@ -74,7 +80,7 @@ static struct rb_node *tree_insert(struc entry = rb_entry(parent, struct btrfs_leaf_ref, rb_node); WARN_ON(!entry->in_tree); - ret = comp_keys(key, &entry->key); + ret = comp_keys(gen, entry->generation, key, &entry->key); if (ret < 0) p = &(*p)->rb_left; else if (ret > 0) @@ -90,7 +96,8 @@ static struct rb_node *tree_insert(struc return NULL; } -static struct rb_node *tree_search(struct rb_root *root, struct btrfs_key *key) +static struct rb_node *tree_search(struct rb_root *root, u64 gen, + struct btrfs_key *key) { struct rb_node * n = root->rb_node; struct btrfs_leaf_ref *entry; @@ -100,7 +107,7 @@ static struct rb_node *tree_search(struc entry = rb_entry(n, struct btrfs_leaf_ref, rb_node); WARN_ON(!entry->in_tree); - ret = comp_keys(key, &entry->key); + ret = comp_keys(gen, entry->generation, key, &entry->key); if (ret < 0) n = n->rb_left; else if (ret > 0) @@ -140,6 +147,7 @@ int btrfs_remove_leaf_refs(struct btrfs_ } struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root, + u64 generation, struct btrfs_key *key) { struct rb_node *rb; @@ -150,10 +158,11 @@ struct btrfs_leaf_ref *btrfs_lookup_leaf return NULL; spin_lock(&tree->lock); - if (tree->last && comp_keys(key, &tree->last->key) == 0) { + if (tree->last && comp_keys(generation, tree->last->generation, + key, &tree->last->key) == 0) { ref = tree->last; } else { - rb = tree_search(&tree->root, key); + rb = tree_search(&tree->root, generation, key); if (rb) { ref = rb_entry(rb, struct btrfs_leaf_ref, rb_node); tree->last = ref; @@ -171,17 +180,15 @@ int btrfs_add_leaf_ref(struct btrfs_root struct rb_node *rb; size_t size = btrfs_leaf_ref_size(ref->nritems); struct btrfs_leaf_ref_tree *tree = root->ref_tree; - struct btrfs_transaction *trans = root->fs_info->running_transaction; spin_lock(&tree->lock); - rb = tree_insert(&tree->root, &ref->key, &ref->rb_node); + rb = tree_insert(&tree->root, ref->generation, &ref->key, + &ref->rb_node); if (rb) { ret = -EEXIST; } else { spin_lock(&root->fs_info->ref_cache_lock); root->fs_info->total_ref_cache_size += size; - if (trans && tree->generation == trans->transid) - root->fs_info->running_ref_cache_size += size; spin_unlock(&root->fs_info->ref_cache_lock); tree->last = ref; @@ -195,15 +202,12 @@ int btrfs_remove_leaf_ref(struct btrfs_r { size_t size = btrfs_leaf_ref_size(ref->nritems); struct btrfs_leaf_ref_tree *tree = root->ref_tree; - struct btrfs_transaction *trans = root->fs_info->running_transaction; BUG_ON(!ref->in_tree); spin_lock(&tree->lock); spin_lock(&root->fs_info->ref_cache_lock); root->fs_info->total_ref_cache_size -= size; - if (trans && tree->generation == trans->transid) - root->fs_info->running_ref_cache_size -= size; spin_unlock(&root->fs_info->ref_cache_lock); if (tree->last == ref) { diff -r cf052b443059 ref-cache.h --- a/ref-cache.h Sun Jul 27 06:39:00 2008 -0400 +++ b/ref-cache.h Mon Jul 28 11:03:42 2008 -0400 @@ -15,6 +15,8 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. */ +#ifndef __REFCACHE__ +#define __REFCACHE__ struct btrfs_extent_info { u64 bytenr; @@ -36,13 +38,6 @@ struct btrfs_leaf_ref { struct btrfs_extent_info extents[]; }; -struct btrfs_leaf_ref_tree { - struct rb_root root; - struct btrfs_leaf_ref *last; - u64 generation; - spinlock_t lock; -}; - static inline size_t btrfs_leaf_ref_size(int nr_extents) { return sizeof(struct btrfs_leaf_ref) + @@ -53,7 +48,6 @@ static inline void btrfs_leaf_ref_tree_i { tree->root.rb_node = NULL; tree->last = NULL; - tree->generation = 0; spin_lock_init(&tree->lock); } @@ -66,7 +60,9 @@ struct btrfs_leaf_ref *btrfs_alloc_leaf_ struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(int nr_extents); void btrfs_free_leaf_ref(struct btrfs_leaf_ref *ref); struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root, - struct btrfs_key *key); + u64 gen, struct btrfs_key *key); int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref); int btrfs_remove_leaf_refs(struct btrfs_root *root); int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref); + +#endif diff -r cf052b443059 transaction.c --- a/transaction.c Sun Jul 27 06:39:00 2008 -0400 +++ b/transaction.c Mon Jul 28 11:03:42 2008 -0400 @@ -36,7 +36,6 @@ struct dirty_root { struct list_head list; struct btrfs_root *root; struct btrfs_root *latest_root; - struct btrfs_leaf_ref_tree ref_tree; }; static noinline void put_transaction(struct btrfs_transaction *transaction) @@ -108,13 +107,13 @@ static noinline int record_root_in_trans dirty->latest_root = root; INIT_LIST_HEAD(&dirty->list); - btrfs_leaf_ref_tree_init(&dirty->ref_tree); - dirty->ref_tree.generation = running_trans_id; root->commit_root = btrfs_root_node(root); - root->ref_tree = &dirty->ref_tree; + root->dirty_root = dirty; memcpy(dirty->root, root, sizeof(*root)); + dirty->root->ref_tree = &root->ref_tree_struct; + spin_lock_init(&dirty->root->node_lock); mutex_init(&dirty->root->objectid_mutex); dirty->root->node = root->commit_root; @@ -333,6 +332,8 @@ int btrfs_commit_tree_roots(struct btrfs list_del_init(next); root = list_entry(next, struct btrfs_root, dirty_list); update_cowonly_root(trans, root); + if (root->fs_info->closing) + btrfs_remove_leaf_refs(root); } return 0; } @@ -346,10 +347,8 @@ int btrfs_add_dead_root(struct btrfs_roo dirty = kmalloc(sizeof(*dirty), GFP_NOFS); if (!dirty) return -ENOMEM; - btrfs_leaf_ref_tree_init(&dirty->ref_tree); dirty->root = root; dirty->latest_root = latest; - root->ref_tree = NULL; list_add(&dirty->list, dead_list); return 0; } @@ -379,18 +378,14 @@ static noinline int add_dirty_roots(stru BTRFS_ROOT_TRANS_TAG); BUG_ON(!root->ref_tree); - dirty = container_of(root->ref_tree, struct dirty_root, - ref_tree); + dirty = root->dirty_root; if (root->commit_root == root->node) { WARN_ON(root->node->start != btrfs_root_bytenr(&root->root_item)); - BUG_ON(!btrfs_leaf_ref_tree_empty( - root->ref_tree)); free_extent_buffer(root->commit_root); root->commit_root = NULL; - root->ref_tree = NULL; kfree(dirty->root); kfree(dirty); @@ -410,7 +405,6 @@ static noinline int add_dirty_roots(stru sizeof(struct btrfs_disk_key)); root->root_item.drop_level = 0; root->commit_root = NULL; - root->ref_tree = NULL; root->root_key.offset = root->fs_info->generation; btrfs_set_root_bytenr(&root->root_item, root->node->start); @@ -538,8 +532,6 @@ static noinline int drop_dirty_roots(str nr = trans->blocks_used; ret = btrfs_end_transaction(trans, tree_root); BUG_ON(ret); - - btrfs_remove_leaf_refs(dirty->root); free_extent_buffer(dirty->root->node); kfree(dirty->root); @@ -725,10 +717,6 @@ int btrfs_commit_transaction(struct btrf &dirty_fs_roots); BUG_ON(ret); - spin_lock(&root->fs_info->ref_cache_lock); - root->fs_info->running_ref_cache_size = 0; - spin_unlock(&root->fs_info->ref_cache_lock); - ret = btrfs_commit_tree_roots(trans, root); BUG_ON(ret);