aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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