aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-07-28 15:32:51 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:05 -0400
commit017e5369eb353559d68a11d4a718faa634533821 (patch)
treec339f2f4a59e403c7f9bfa8d137663c6bf260537 /fs
parent31153d81284934601d08110ac7698fd9a535e4c0 (diff)
Btrfs: Leaf reference cache update
This changes the reference cache to make a single cache per root instead of one cache per transaction, and to key by the byte number of the disk block instead of the keys inside. This makes it much less likely to have cache misses if a snapshot or something has an extra reference on a higher node or a leaf while the first transaction that added the leaf into the cache is dropping. Some throttling is added to functions that free blocks heavily so they wait for old transactions to drop. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h11
-rw-r--r--fs/btrfs/disk-io.c8
-rw-r--r--fs/btrfs/extent-tree.c18
-rw-r--r--fs/btrfs/file.c2
-rw-r--r--fs/btrfs/inode.c8
-rw-r--r--fs/btrfs/ref-cache.c71
-rw-r--r--fs/btrfs/ref-cache.h18
-rw-r--r--fs/btrfs/transaction.c34
8 files changed, 61 insertions, 109 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 34ed23d64eb5..4eca0aa1ce74 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -594,7 +594,6 @@ struct btrfs_fs_info {
594 594
595 spinlock_t ref_cache_lock; 595 spinlock_t ref_cache_lock;
596 u64 total_ref_cache_size; 596 u64 total_ref_cache_size;
597 u64 running_ref_cache_size;
598 597
599 u64 avail_data_alloc_bits; 598 u64 avail_data_alloc_bits;
600 u64 avail_metadata_alloc_bits; 599 u64 avail_metadata_alloc_bits;
@@ -606,10 +605,18 @@ struct btrfs_fs_info {
606 void *bdev_holder; 605 void *bdev_holder;
607}; 606};
608 607
608struct btrfs_leaf_ref_tree {
609 struct rb_root root;
610 struct btrfs_leaf_ref *last;
611 struct list_head list;
612 spinlock_t lock;
613};
614
609/* 615/*
610 * in ram representation of the tree. extent_root is used for all allocations 616 * in ram representation of the tree. extent_root is used for all allocations
611 * and for the extent tree extent_root root. 617 * and for the extent tree extent_root root.
612 */ 618 */
619struct dirty_root;
613struct btrfs_root { 620struct btrfs_root {
614 struct extent_buffer *node; 621 struct extent_buffer *node;
615 622
@@ -618,6 +625,8 @@ struct btrfs_root {
618 625
619 struct extent_buffer *commit_root; 626 struct extent_buffer *commit_root;
620 struct btrfs_leaf_ref_tree *ref_tree; 627 struct btrfs_leaf_ref_tree *ref_tree;
628 struct btrfs_leaf_ref_tree ref_tree_struct;
629 struct dirty_root *dirty_root;
621 630
622 struct btrfs_root_item root_item; 631 struct btrfs_root_item root_item;
623 struct btrfs_key root_key; 632 struct btrfs_key root_key;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 4f0e1d06c384..eccdf13a95ac 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -40,6 +40,7 @@
40#include "print-tree.h" 40#include "print-tree.h"
41#include "async-thread.h" 41#include "async-thread.h"
42#include "locking.h" 42#include "locking.h"
43#include "ref-cache.h"
43 44
44#if 0 45#if 0
45static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf) 46static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
@@ -737,6 +738,10 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
737 spin_lock_init(&root->node_lock); 738 spin_lock_init(&root->node_lock);
738 spin_lock_init(&root->orphan_lock); 739 spin_lock_init(&root->orphan_lock);
739 mutex_init(&root->objectid_mutex); 740 mutex_init(&root->objectid_mutex);
741
742 btrfs_leaf_ref_tree_init(&root->ref_tree_struct);
743 root->ref_tree = &root->ref_tree_struct;
744
740 memset(&root->root_key, 0, sizeof(root->root_key)); 745 memset(&root->root_key, 0, sizeof(root->root_key));
741 memset(&root->root_item, 0, sizeof(root->root_item)); 746 memset(&root->root_item, 0, sizeof(root->root_item));
742 memset(&root->defrag_progress, 0, sizeof(root->defrag_progress)); 747 memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
@@ -1176,9 +1181,6 @@ static int transaction_kthread(void *arg)
1176 goto sleep; 1181 goto sleep;
1177 } 1182 }
1178 1183
1179 printk("btrfs: running reference cache size %Lu\n",
1180 root->fs_info->running_ref_cache_size);
1181
1182 now = get_seconds(); 1184 now = get_seconds();
1183 if (now < cur->start_time || now - cur->start_time < 30) { 1185 if (now < cur->start_time || now - cur->start_time < 30) {
1184 mutex_unlock(&root->fs_info->trans_mutex); 1186 mutex_unlock(&root->fs_info->trans_mutex);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 7b24f1511654..0e294cfaa60c 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1004,8 +1004,6 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
1004 goto out; 1004 goto out;
1005 } 1005 }
1006 1006
1007 btrfs_item_key_to_cpu(buf, &ref->key, 0);
1008
1009 ref->bytenr = buf->start; 1007 ref->bytenr = buf->start;
1010 ref->owner = btrfs_header_owner(buf); 1008 ref->owner = btrfs_header_owner(buf);
1011 ref->generation = btrfs_header_generation(buf); 1009 ref->generation = btrfs_header_generation(buf);
@@ -2387,19 +2385,15 @@ static void noinline reada_walk_down(struct btrfs_root *root,
2387 } 2385 }
2388} 2386}
2389 2387
2390/*
2391 * we want to avoid as much random IO as we can with the alloc mutex
2392 * held, so drop the lock and do the lookup, then do it again with the
2393 * lock held.
2394 */
2395int drop_snap_lookup_refcount(struct btrfs_root *root, u64 start, u64 len, 2388int drop_snap_lookup_refcount(struct btrfs_root *root, u64 start, u64 len,
2396 u32 *refs) 2389 u32 *refs)
2397{ 2390{
2391 int ret;
2398 mutex_unlock(&root->fs_info->alloc_mutex); 2392 mutex_unlock(&root->fs_info->alloc_mutex);
2399 lookup_extent_ref(NULL, root, start, len, refs); 2393 ret = lookup_extent_ref(NULL, root, start, len, refs);
2400 cond_resched(); 2394 cond_resched();
2401 mutex_lock(&root->fs_info->alloc_mutex); 2395 mutex_lock(&root->fs_info->alloc_mutex);
2402 return lookup_extent_ref(NULL, root, start, len, refs); 2396 return ret;
2403} 2397}
2404 2398
2405/* 2399/*
@@ -2468,11 +2462,11 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
2468 BUG_ON(ret); 2462 BUG_ON(ret);
2469 continue; 2463 continue;
2470 } 2464 }
2471 2465
2472 if (*level == 1) { 2466 if (*level == 1) {
2473 struct btrfs_key key; 2467 struct btrfs_key key;
2474 btrfs_node_key_to_cpu(cur, &key, path->slots[*level]); 2468 btrfs_node_key_to_cpu(cur, &key, path->slots[*level]);
2475 ref = btrfs_lookup_leaf_ref(root, &key); 2469 ref = btrfs_lookup_leaf_ref(root, bytenr);
2476 if (ref) { 2470 if (ref) {
2477 ret = drop_leaf_ref(trans, root, ref); 2471 ret = drop_leaf_ref(trans, root, ref);
2478 BUG_ON(ret); 2472 BUG_ON(ret);
@@ -2482,7 +2476,6 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
2482 break; 2476 break;
2483 } 2477 }
2484 } 2478 }
2485
2486 next = btrfs_find_tree_block(root, bytenr, blocksize); 2479 next = btrfs_find_tree_block(root, bytenr, blocksize);
2487 if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) { 2480 if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) {
2488 free_extent_buffer(next); 2481 free_extent_buffer(next);
@@ -2672,6 +2665,7 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
2672 ret = -EAGAIN; 2665 ret = -EAGAIN;
2673 break; 2666 break;
2674 } 2667 }
2668 wake_up(&root->fs_info->transaction_throttle);
2675 } 2669 }
2676 for (i = 0; i <= orig_level; i++) { 2670 for (i = 0; i <= orig_level; i++) {
2677 if (path->nodes[i]) { 2671 if (path->nodes[i]) {
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index e5ffb66ad320..3efec25e34b0 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -347,7 +347,7 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans,
347 btrfs_update_inode(trans, root, inode); 347 btrfs_update_inode(trans, root, inode);
348 } 348 }
349failed: 349failed:
350 err = btrfs_end_transaction_throttle(trans, root); 350 err = btrfs_end_transaction(trans, root);
351out_unlock: 351out_unlock:
352 unlock_extent(io_tree, start_pos, end_of_last_block, GFP_NOFS); 352 unlock_extent(io_tree, start_pos, end_of_last_block, GFP_NOFS);
353 return err; 353 return err;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index cf9534b79aba..4f977ea5497e 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2482,7 +2482,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
2482 btrfs_update_inode_block_group(trans, dir); 2482 btrfs_update_inode_block_group(trans, dir);
2483out_unlock: 2483out_unlock:
2484 nr = trans->blocks_used; 2484 nr = trans->blocks_used;
2485 btrfs_end_transaction_throttle(trans, root); 2485 btrfs_end_transaction(trans, root);
2486fail: 2486fail:
2487 if (drop_inode) { 2487 if (drop_inode) {
2488 inode_dec_link_count(inode); 2488 inode_dec_link_count(inode);
@@ -2535,7 +2535,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
2535 drop_inode = 1; 2535 drop_inode = 1;
2536 2536
2537 nr = trans->blocks_used; 2537 nr = trans->blocks_used;
2538 btrfs_end_transaction_throttle(trans, root); 2538 btrfs_end_transaction(trans, root);
2539fail: 2539fail:
2540 if (drop_inode) { 2540 if (drop_inode) {
2541 inode_dec_link_count(inode); 2541 inode_dec_link_count(inode);
@@ -2609,7 +2609,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
2609 2609
2610out_fail: 2610out_fail:
2611 nr = trans->blocks_used; 2611 nr = trans->blocks_used;
2612 btrfs_end_transaction_throttle(trans, root); 2612 btrfs_end_transaction(trans, root);
2613 2613
2614out_unlock: 2614out_unlock:
2615 if (drop_on_err) 2615 if (drop_on_err)
@@ -3548,7 +3548,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
3548 3548
3549out_unlock: 3549out_unlock:
3550 nr = trans->blocks_used; 3550 nr = trans->blocks_used;
3551 btrfs_end_transaction_throttle(trans, root); 3551 btrfs_end_transaction(trans, root);
3552out_fail: 3552out_fail:
3553 if (drop_inode) { 3553 if (drop_inode) {
3554 inode_dec_link_count(inode); 3554 inode_dec_link_count(inode);
diff --git a/fs/btrfs/ref-cache.c b/fs/btrfs/ref-cache.c
index 95a9faeb9dc4..ec9587784a3d 100644
--- a/fs/btrfs/ref-cache.c
+++ b/fs/btrfs/ref-cache.c
@@ -29,6 +29,7 @@ struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(int nr_extents)
29 if (ref) { 29 if (ref) {
30 memset(ref, 0, sizeof(*ref)); 30 memset(ref, 0, sizeof(*ref));
31 atomic_set(&ref->usage, 1); 31 atomic_set(&ref->usage, 1);
32 INIT_LIST_HEAD(&ref->list);
32 } 33 }
33 return ref; 34 return ref;
34} 35}
@@ -44,40 +45,21 @@ void btrfs_free_leaf_ref(struct btrfs_leaf_ref *ref)
44 } 45 }
45} 46}
46 47
47static int comp_keys(struct btrfs_key *k1, struct btrfs_key *k2) 48static struct rb_node *tree_insert(struct rb_root *root, u64 bytenr,
48{
49 if (k1->objectid > k2->objectid)
50 return 1;
51 if (k1->objectid < k2->objectid)
52 return -1;
53 if (k1->type > k2->type)
54 return 1;
55 if (k1->type < k2->type)
56 return -1;
57 if (k1->offset > k2->offset)
58 return 1;
59 if (k1->offset < k2->offset)
60 return -1;
61 return 0;
62}
63
64static struct rb_node *tree_insert(struct rb_root *root, struct btrfs_key *key,
65 struct rb_node *node) 49 struct rb_node *node)
66{ 50{
67 struct rb_node ** p = &root->rb_node; 51 struct rb_node ** p = &root->rb_node;
68 struct rb_node * parent = NULL; 52 struct rb_node * parent = NULL;
69 struct btrfs_leaf_ref *entry; 53 struct btrfs_leaf_ref *entry;
70 int ret;
71 54
72 while(*p) { 55 while(*p) {
73 parent = *p; 56 parent = *p;
74 entry = rb_entry(parent, struct btrfs_leaf_ref, rb_node); 57 entry = rb_entry(parent, struct btrfs_leaf_ref, rb_node);
75 WARN_ON(!entry->in_tree); 58 WARN_ON(!entry->in_tree);
76 59
77 ret = comp_keys(key, &entry->key); 60 if (bytenr < entry->bytenr)
78 if (ret < 0)
79 p = &(*p)->rb_left; 61 p = &(*p)->rb_left;
80 else if (ret > 0) 62 else if (bytenr > entry->bytenr)
81 p = &(*p)->rb_right; 63 p = &(*p)->rb_right;
82 else 64 else
83 return parent; 65 return parent;
@@ -90,20 +72,18 @@ static struct rb_node *tree_insert(struct rb_root *root, struct btrfs_key *key,
90 return NULL; 72 return NULL;
91} 73}
92 74
93static struct rb_node *tree_search(struct rb_root *root, struct btrfs_key *key) 75static struct rb_node *tree_search(struct rb_root *root, u64 bytenr)
94{ 76{
95 struct rb_node * n = root->rb_node; 77 struct rb_node * n = root->rb_node;
96 struct btrfs_leaf_ref *entry; 78 struct btrfs_leaf_ref *entry;
97 int ret;
98 79
99 while(n) { 80 while(n) {
100 entry = rb_entry(n, struct btrfs_leaf_ref, rb_node); 81 entry = rb_entry(n, struct btrfs_leaf_ref, rb_node);
101 WARN_ON(!entry->in_tree); 82 WARN_ON(!entry->in_tree);
102 83
103 ret = comp_keys(key, &entry->key); 84 if (bytenr < entry->bytenr)
104 if (ret < 0)
105 n = n->rb_left; 85 n = n->rb_left;
106 else if (ret > 0) 86 else if (bytenr > entry->bytenr)
107 n = n->rb_right; 87 n = n->rb_right;
108 else 88 else
109 return n; 89 return n;
@@ -122,11 +102,11 @@ int btrfs_remove_leaf_refs(struct btrfs_root *root)
122 102
123 spin_lock(&tree->lock); 103 spin_lock(&tree->lock);
124 while(!btrfs_leaf_ref_tree_empty(tree)) { 104 while(!btrfs_leaf_ref_tree_empty(tree)) {
125 tree->last = NULL;
126 rb = rb_first(&tree->root); 105 rb = rb_first(&tree->root);
127 ref = rb_entry(rb, struct btrfs_leaf_ref, rb_node); 106 ref = rb_entry(rb, struct btrfs_leaf_ref, rb_node);
128 rb_erase(&ref->rb_node, &tree->root); 107 rb_erase(&ref->rb_node, &tree->root);
129 ref->in_tree = 0; 108 ref->in_tree = 0;
109 list_del_init(&ref->list);
130 110
131 spin_unlock(&tree->lock); 111 spin_unlock(&tree->lock);
132 112
@@ -140,7 +120,7 @@ int btrfs_remove_leaf_refs(struct btrfs_root *root)
140} 120}
141 121
142struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root, 122struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root,
143 struct btrfs_key *key) 123 u64 bytenr)
144{ 124{
145 struct rb_node *rb; 125 struct rb_node *rb;
146 struct btrfs_leaf_ref *ref = NULL; 126 struct btrfs_leaf_ref *ref = NULL;
@@ -150,15 +130,9 @@ struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root,
150 return NULL; 130 return NULL;
151 131
152 spin_lock(&tree->lock); 132 spin_lock(&tree->lock);
153 if (tree->last && comp_keys(key, &tree->last->key) == 0) { 133 rb = tree_search(&tree->root, bytenr);
154 ref = tree->last; 134 if (rb)
155 } else { 135 ref = rb_entry(rb, struct btrfs_leaf_ref, rb_node);
156 rb = tree_search(&tree->root, key);
157 if (rb) {
158 ref = rb_entry(rb, struct btrfs_leaf_ref, rb_node);
159 tree->last = ref;
160 }
161 }
162 if (ref) 136 if (ref)
163 atomic_inc(&ref->usage); 137 atomic_inc(&ref->usage);
164 spin_unlock(&tree->lock); 138 spin_unlock(&tree->lock);
@@ -171,21 +145,17 @@ int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref)
171 struct rb_node *rb; 145 struct rb_node *rb;
172 size_t size = btrfs_leaf_ref_size(ref->nritems); 146 size_t size = btrfs_leaf_ref_size(ref->nritems);
173 struct btrfs_leaf_ref_tree *tree = root->ref_tree; 147 struct btrfs_leaf_ref_tree *tree = root->ref_tree;
174 struct btrfs_transaction *trans = root->fs_info->running_transaction;
175 148
176 spin_lock(&tree->lock); 149 spin_lock(&tree->lock);
177 rb = tree_insert(&tree->root, &ref->key, &ref->rb_node); 150 rb = tree_insert(&tree->root, ref->bytenr, &ref->rb_node);
178 if (rb) { 151 if (rb) {
179 ret = -EEXIST; 152 ret = -EEXIST;
180 } else { 153 } else {
181 spin_lock(&root->fs_info->ref_cache_lock); 154 spin_lock(&root->fs_info->ref_cache_lock);
182 root->fs_info->total_ref_cache_size += size; 155 root->fs_info->total_ref_cache_size += size;
183 if (trans && tree->generation == trans->transid)
184 root->fs_info->running_ref_cache_size += size;
185 spin_unlock(&root->fs_info->ref_cache_lock); 156 spin_unlock(&root->fs_info->ref_cache_lock);
186
187 tree->last = ref;
188 atomic_inc(&ref->usage); 157 atomic_inc(&ref->usage);
158 list_add_tail(&ref->list, &tree->list);
189 } 159 }
190 spin_unlock(&tree->lock); 160 spin_unlock(&tree->lock);
191 return ret; 161 return ret;
@@ -195,28 +165,17 @@ int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref)
195{ 165{
196 size_t size = btrfs_leaf_ref_size(ref->nritems); 166 size_t size = btrfs_leaf_ref_size(ref->nritems);
197 struct btrfs_leaf_ref_tree *tree = root->ref_tree; 167 struct btrfs_leaf_ref_tree *tree = root->ref_tree;
198 struct btrfs_transaction *trans = root->fs_info->running_transaction;
199 168
200 BUG_ON(!ref->in_tree); 169 BUG_ON(!ref->in_tree);
201 spin_lock(&tree->lock); 170 spin_lock(&tree->lock);
202 171
203 spin_lock(&root->fs_info->ref_cache_lock); 172 spin_lock(&root->fs_info->ref_cache_lock);
204 root->fs_info->total_ref_cache_size -= size; 173 root->fs_info->total_ref_cache_size -= size;
205 if (trans && tree->generation == trans->transid)
206 root->fs_info->running_ref_cache_size -= size;
207 spin_unlock(&root->fs_info->ref_cache_lock); 174 spin_unlock(&root->fs_info->ref_cache_lock);
208 175
209 if (tree->last == ref) {
210 struct rb_node *next = rb_next(&ref->rb_node);
211 if (next) {
212 tree->last = rb_entry(next, struct btrfs_leaf_ref,
213 rb_node);
214 } else
215 tree->last = NULL;
216 }
217
218 rb_erase(&ref->rb_node, &tree->root); 176 rb_erase(&ref->rb_node, &tree->root);
219 ref->in_tree = 0; 177 ref->in_tree = 0;
178 list_del_init(&ref->list);
220 179
221 spin_unlock(&tree->lock); 180 spin_unlock(&tree->lock);
222 181
diff --git a/fs/btrfs/ref-cache.h b/fs/btrfs/ref-cache.h
index 79ecc47110f2..823c049f72f1 100644
--- a/fs/btrfs/ref-cache.h
+++ b/fs/btrfs/ref-cache.h
@@ -15,6 +15,8 @@
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA. 16 * Boston, MA 021110-1307, USA.
17 */ 17 */
18#ifndef __REFCACHE__
19#define __REFCACHE__
18 20
19struct btrfs_extent_info { 21struct btrfs_extent_info {
20 u64 bytenr; 22 u64 bytenr;
@@ -25,7 +27,6 @@ struct btrfs_extent_info {
25 27
26struct btrfs_leaf_ref { 28struct btrfs_leaf_ref {
27 struct rb_node rb_node; 29 struct rb_node rb_node;
28 struct btrfs_key key;
29 int in_tree; 30 int in_tree;
30 atomic_t usage; 31 atomic_t usage;
31 32
@@ -33,14 +34,9 @@ struct btrfs_leaf_ref {
33 u64 owner; 34 u64 owner;
34 u64 generation; 35 u64 generation;
35 int nritems; 36 int nritems;
36 struct btrfs_extent_info extents[];
37};
38 37
39struct btrfs_leaf_ref_tree { 38 struct list_head list;
40 struct rb_root root; 39 struct btrfs_extent_info extents[];
41 struct btrfs_leaf_ref *last;
42 u64 generation;
43 spinlock_t lock;
44}; 40};
45 41
46static inline size_t btrfs_leaf_ref_size(int nr_extents) 42static inline size_t btrfs_leaf_ref_size(int nr_extents)
@@ -53,7 +49,7 @@ static inline void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree)
53{ 49{
54 tree->root.rb_node = NULL; 50 tree->root.rb_node = NULL;
55 tree->last = NULL; 51 tree->last = NULL;
56 tree->generation = 0; 52 INIT_LIST_HEAD(&tree->list);
57 spin_lock_init(&tree->lock); 53 spin_lock_init(&tree->lock);
58} 54}
59 55
@@ -66,7 +62,9 @@ void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree);
66struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(int nr_extents); 62struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(int nr_extents);
67void btrfs_free_leaf_ref(struct btrfs_leaf_ref *ref); 63void btrfs_free_leaf_ref(struct btrfs_leaf_ref *ref);
68struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root, 64struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root,
69 struct btrfs_key *key); 65 u64 bytenr);
70int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref); 66int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref);
71int btrfs_remove_leaf_refs(struct btrfs_root *root); 67int btrfs_remove_leaf_refs(struct btrfs_root *root);
72int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref); 68int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref);
69
70#endif
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 543e5ee4033a..fcef3cae0c92 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -36,7 +36,6 @@ struct dirty_root {
36 struct list_head list; 36 struct list_head list;
37 struct btrfs_root *root; 37 struct btrfs_root *root;
38 struct btrfs_root *latest_root; 38 struct btrfs_root *latest_root;
39 struct btrfs_leaf_ref_tree ref_tree;
40}; 39};
41 40
42static noinline void put_transaction(struct btrfs_transaction *transaction) 41static noinline void put_transaction(struct btrfs_transaction *transaction)
@@ -108,13 +107,13 @@ static noinline int record_root_in_trans(struct btrfs_root *root)
108 107
109 dirty->latest_root = root; 108 dirty->latest_root = root;
110 INIT_LIST_HEAD(&dirty->list); 109 INIT_LIST_HEAD(&dirty->list);
111 btrfs_leaf_ref_tree_init(&dirty->ref_tree);
112 dirty->ref_tree.generation = running_trans_id;
113 110
114 root->commit_root = btrfs_root_node(root); 111 root->commit_root = btrfs_root_node(root);
115 root->ref_tree = &dirty->ref_tree; 112 root->dirty_root = dirty;
116 113
117 memcpy(dirty->root, root, sizeof(*root)); 114 memcpy(dirty->root, root, sizeof(*root));
115 dirty->root->ref_tree = &root->ref_tree_struct;
116
118 spin_lock_init(&dirty->root->node_lock); 117 spin_lock_init(&dirty->root->node_lock);
119 mutex_init(&dirty->root->objectid_mutex); 118 mutex_init(&dirty->root->objectid_mutex);
120 dirty->root->node = root->commit_root; 119 dirty->root->node = root->commit_root;
@@ -217,12 +216,13 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
217 if (waitqueue_active(&cur_trans->writer_wait)) 216 if (waitqueue_active(&cur_trans->writer_wait))
218 wake_up(&cur_trans->writer_wait); 217 wake_up(&cur_trans->writer_wait);
219 218
220 if (0 && cur_trans->in_commit && throttle) { 219 if (throttle && atomic_read(&root->fs_info->throttles)) {
221 DEFINE_WAIT(wait); 220 DEFINE_WAIT(wait);
222 mutex_unlock(&root->fs_info->trans_mutex); 221 mutex_unlock(&root->fs_info->trans_mutex);
223 prepare_to_wait(&root->fs_info->transaction_throttle, &wait, 222 prepare_to_wait(&root->fs_info->transaction_throttle, &wait,
224 TASK_UNINTERRUPTIBLE); 223 TASK_UNINTERRUPTIBLE);
225 schedule(); 224 if (atomic_read(&root->fs_info->throttles))
225 schedule();
226 finish_wait(&root->fs_info->transaction_throttle, &wait); 226 finish_wait(&root->fs_info->transaction_throttle, &wait);
227 mutex_lock(&root->fs_info->trans_mutex); 227 mutex_lock(&root->fs_info->trans_mutex);
228 } 228 }
@@ -333,6 +333,8 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
333 list_del_init(next); 333 list_del_init(next);
334 root = list_entry(next, struct btrfs_root, dirty_list); 334 root = list_entry(next, struct btrfs_root, dirty_list);
335 update_cowonly_root(trans, root); 335 update_cowonly_root(trans, root);
336 if (root->fs_info->closing)
337 btrfs_remove_leaf_refs(root);
336 } 338 }
337 return 0; 339 return 0;
338} 340}
@@ -346,10 +348,8 @@ int btrfs_add_dead_root(struct btrfs_root *root,
346 dirty = kmalloc(sizeof(*dirty), GFP_NOFS); 348 dirty = kmalloc(sizeof(*dirty), GFP_NOFS);
347 if (!dirty) 349 if (!dirty)
348 return -ENOMEM; 350 return -ENOMEM;
349 btrfs_leaf_ref_tree_init(&dirty->ref_tree);
350 dirty->root = root; 351 dirty->root = root;
351 dirty->latest_root = latest; 352 dirty->latest_root = latest;
352 root->ref_tree = NULL;
353 list_add(&dirty->list, dead_list); 353 list_add(&dirty->list, dead_list);
354 return 0; 354 return 0;
355} 355}
@@ -379,18 +379,14 @@ static noinline int add_dirty_roots(struct btrfs_trans_handle *trans,
379 BTRFS_ROOT_TRANS_TAG); 379 BTRFS_ROOT_TRANS_TAG);
380 380
381 BUG_ON(!root->ref_tree); 381 BUG_ON(!root->ref_tree);
382 dirty = container_of(root->ref_tree, struct dirty_root, 382 dirty = root->dirty_root;
383 ref_tree);
384 383
385 if (root->commit_root == root->node) { 384 if (root->commit_root == root->node) {
386 WARN_ON(root->node->start != 385 WARN_ON(root->node->start !=
387 btrfs_root_bytenr(&root->root_item)); 386 btrfs_root_bytenr(&root->root_item));
388 387
389 BUG_ON(!btrfs_leaf_ref_tree_empty(
390 root->ref_tree));
391 free_extent_buffer(root->commit_root); 388 free_extent_buffer(root->commit_root);
392 root->commit_root = NULL; 389 root->commit_root = NULL;
393 root->ref_tree = NULL;
394 390
395 kfree(dirty->root); 391 kfree(dirty->root);
396 kfree(dirty); 392 kfree(dirty);
@@ -410,7 +406,6 @@ static noinline int add_dirty_roots(struct btrfs_trans_handle *trans,
410 sizeof(struct btrfs_disk_key)); 406 sizeof(struct btrfs_disk_key));
411 root->root_item.drop_level = 0; 407 root->root_item.drop_level = 0;
412 root->commit_root = NULL; 408 root->commit_root = NULL;
413 root->ref_tree = NULL;
414 root->root_key.offset = root->fs_info->generation; 409 root->root_key.offset = root->fs_info->generation;
415 btrfs_set_root_bytenr(&root->root_item, 410 btrfs_set_root_bytenr(&root->root_item,
416 root->node->start); 411 root->node->start);
@@ -485,7 +480,7 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
485 while(!list_empty(list)) { 480 while(!list_empty(list)) {
486 struct btrfs_root *root; 481 struct btrfs_root *root;
487 482
488 dirty = list_entry(list->next, struct dirty_root, list); 483 dirty = list_entry(list->prev, struct dirty_root, list);
489 list_del_init(&dirty->list); 484 list_del_init(&dirty->list);
490 485
491 num_bytes = btrfs_root_used(&dirty->root->root_item); 486 num_bytes = btrfs_root_used(&dirty->root->root_item);
@@ -507,7 +502,7 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
507 if (err) 502 if (err)
508 ret = err; 503 ret = err;
509 nr = trans->blocks_used; 504 nr = trans->blocks_used;
510 ret = btrfs_end_transaction_throttle(trans, tree_root); 505 ret = btrfs_end_transaction(trans, tree_root);
511 BUG_ON(ret); 506 BUG_ON(ret);
512 507
513 mutex_unlock(&root->fs_info->drop_mutex); 508 mutex_unlock(&root->fs_info->drop_mutex);
@@ -517,6 +512,7 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
517 } 512 }
518 BUG_ON(ret); 513 BUG_ON(ret);
519 atomic_dec(&root->fs_info->throttles); 514 atomic_dec(&root->fs_info->throttles);
515 wake_up(&root->fs_info->transaction_throttle);
520 516
521 mutex_lock(&root->fs_info->alloc_mutex); 517 mutex_lock(&root->fs_info->alloc_mutex);
522 num_bytes -= btrfs_root_used(&dirty->root->root_item); 518 num_bytes -= btrfs_root_used(&dirty->root->root_item);
@@ -539,8 +535,6 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
539 ret = btrfs_end_transaction(trans, tree_root); 535 ret = btrfs_end_transaction(trans, tree_root);
540 BUG_ON(ret); 536 BUG_ON(ret);
541 537
542 btrfs_remove_leaf_refs(dirty->root);
543
544 free_extent_buffer(dirty->root->node); 538 free_extent_buffer(dirty->root->node);
545 kfree(dirty->root); 539 kfree(dirty->root);
546 kfree(dirty); 540 kfree(dirty);
@@ -725,10 +719,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
725 &dirty_fs_roots); 719 &dirty_fs_roots);
726 BUG_ON(ret); 720 BUG_ON(ret);
727 721
728 spin_lock(&root->fs_info->ref_cache_lock);
729 root->fs_info->running_ref_cache_size = 0;
730 spin_unlock(&root->fs_info->ref_cache_lock);
731
732 ret = btrfs_commit_tree_roots(trans, root); 722 ret = btrfs_commit_tree_roots(trans, root);
733 BUG_ON(ret); 723 BUG_ON(ret);
734 724