aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.c1
-rw-r--r--fs/btrfs/ctree.h3
-rw-r--r--fs/btrfs/dir-item.c1
-rw-r--r--fs/btrfs/disk-io.c5
-rw-r--r--fs/btrfs/extent-tree.c18
-rw-r--r--fs/btrfs/extent_io.c1
-rw-r--r--fs/btrfs/file-item.c1
-rw-r--r--fs/btrfs/file.c1
-rw-r--r--fs/btrfs/inode.c22
-rw-r--r--fs/btrfs/locking.c1
-rw-r--r--fs/btrfs/print-tree.c1
-rw-r--r--fs/btrfs/ref-cache.c48
-rw-r--r--fs/btrfs/ref-cache.h11
-rw-r--r--fs/btrfs/transaction.c40
-rw-r--r--fs/btrfs/volumes.c1
15 files changed, 86 insertions, 69 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 245eb00435dd..c4792062dd53 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -3275,4 +3275,3 @@ int btrfs_previous_item(struct btrfs_root *root,
3275 } 3275 }
3276 return 1; 3276 return 1;
3277} 3277}
3278
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 83422088c629..be16cd49ef69 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -666,7 +666,8 @@ struct btrfs_root {
666 /* the dirty list is only used by non-reference counted roots */ 666 /* the dirty list is only used by non-reference counted roots */
667 struct list_head dirty_list; 667 struct list_head dirty_list;
668 668
669 spinlock_t orphan_lock; 669 spinlock_t list_lock;
670 struct list_head dead_list;
670 struct list_head orphan_list; 671 struct list_head orphan_list;
671}; 672};
672 673
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index eb4dd3d75cf9..125094617fe8 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -340,4 +340,3 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
340 } 340 }
341 return 0; 341 return 0;
342} 342}
343
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index ec1ba8ddb35f..e826730d750f 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -735,8 +735,9 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
735 735
736 INIT_LIST_HEAD(&root->dirty_list); 736 INIT_LIST_HEAD(&root->dirty_list);
737 INIT_LIST_HEAD(&root->orphan_list); 737 INIT_LIST_HEAD(&root->orphan_list);
738 INIT_LIST_HEAD(&root->dead_list);
738 spin_lock_init(&root->node_lock); 739 spin_lock_init(&root->node_lock);
739 spin_lock_init(&root->orphan_lock); 740 spin_lock_init(&root->list_lock);
740 mutex_init(&root->objectid_mutex); 741 mutex_init(&root->objectid_mutex);
741 742
742 btrfs_leaf_ref_tree_init(&root->ref_tree_struct); 743 btrfs_leaf_ref_tree_init(&root->ref_tree_struct);
@@ -1717,7 +1718,7 @@ int close_ctree(struct btrfs_root *root)
1717 printk("btrfs: at umount reference cache size %Lu\n", 1718 printk("btrfs: at umount reference cache size %Lu\n",
1718 fs_info->total_ref_cache_size); 1719 fs_info->total_ref_cache_size);
1719 } 1720 }
1720 1721
1721 if (fs_info->extent_root->node) 1722 if (fs_info->extent_root->node)
1722 free_extent_buffer(fs_info->extent_root->node); 1723 free_extent_buffer(fs_info->extent_root->node);
1723 1724
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index fe1ddbd2bfd6..37ca8df30c30 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -867,8 +867,8 @@ static int get_reference_status(struct btrfs_root *root, u64 bytenr,
867 /* 867 /*
868 * For (parent_gen > 0 && parent_gen > ref_gen): 868 * For (parent_gen > 0 && parent_gen > ref_gen):
869 * 869 *
870 * we reach here through the oldest root, therefore 870 * we reach here through the oldest root, therefore
871 * all other reference from same snapshot should have 871 * all other reference from same snapshot should have
872 * a larger generation. 872 * a larger generation.
873 */ 873 */
874 if ((root_objectid != btrfs_ref_root(leaf, ref_item)) || 874 if ((root_objectid != btrfs_ref_root(leaf, ref_item)) ||
@@ -954,7 +954,7 @@ int btrfs_cross_ref_exists(struct btrfs_root *root,
954 if (!eb) 954 if (!eb)
955 continue; 955 continue;
956 extent_start = eb->start; 956 extent_start = eb->start;
957 } else 957 } else
958 extent_start = bytenr; 958 extent_start = bytenr;
959 959
960 ret = get_reference_status(root, extent_start, ref_generation, 960 ret = get_reference_status(root, extent_start, ref_generation,
@@ -1048,7 +1048,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
1048 struct btrfs_leaf_ref *ref; 1048 struct btrfs_leaf_ref *ref;
1049 struct btrfs_extent_info *info; 1049 struct btrfs_extent_info *info;
1050 1050
1051 ref = btrfs_alloc_leaf_ref(nr_file_extents); 1051 ref = btrfs_alloc_leaf_ref(root, nr_file_extents);
1052 if (!ref) { 1052 if (!ref) {
1053 WARN_ON(1); 1053 WARN_ON(1);
1054 goto out; 1054 goto out;
@@ -1059,7 +1059,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
1059 ref->generation = btrfs_header_generation(buf); 1059 ref->generation = btrfs_header_generation(buf);
1060 ref->nritems = nr_file_extents; 1060 ref->nritems = nr_file_extents;
1061 info = ref->extents; 1061 info = ref->extents;
1062 1062
1063 for (i = 0; nr_file_extents > 0 && i < nritems; i++) { 1063 for (i = 0; nr_file_extents > 0 && i < nritems; i++) {
1064 u64 disk_bytenr; 1064 u64 disk_bytenr;
1065 btrfs_item_key_to_cpu(buf, &key, i); 1065 btrfs_item_key_to_cpu(buf, &key, i);
@@ -1085,7 +1085,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
1085 BUG_ON(!root->ref_tree); 1085 BUG_ON(!root->ref_tree);
1086 ret = btrfs_add_leaf_ref(root, ref); 1086 ret = btrfs_add_leaf_ref(root, ref);
1087 WARN_ON(ret); 1087 WARN_ON(ret);
1088 btrfs_free_leaf_ref(ref); 1088 btrfs_free_leaf_ref(root, ref);
1089 } 1089 }
1090out: 1090out:
1091 return 0; 1091 return 0;
@@ -2316,7 +2316,7 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
2316} 2316}
2317 2317
2318static int noinline drop_leaf_ref_no_cache(struct btrfs_trans_handle *trans, 2318static int noinline drop_leaf_ref_no_cache(struct btrfs_trans_handle *trans,
2319 struct btrfs_root *root, 2319 struct btrfs_root *root,
2320 struct extent_buffer *leaf) 2320 struct extent_buffer *leaf)
2321{ 2321{
2322 u64 leaf_owner; 2322 u64 leaf_owner;
@@ -2367,7 +2367,7 @@ static int noinline drop_leaf_ref_no_cache(struct btrfs_trans_handle *trans,
2367} 2367}
2368 2368
2369static int noinline drop_leaf_ref(struct btrfs_trans_handle *trans, 2369static int noinline drop_leaf_ref(struct btrfs_trans_handle *trans,
2370 struct btrfs_root *root, 2370 struct btrfs_root *root,
2371 struct btrfs_leaf_ref *ref) 2371 struct btrfs_leaf_ref *ref)
2372{ 2372{
2373 int i; 2373 int i;
@@ -2521,7 +2521,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
2521 ret = drop_leaf_ref(trans, root, ref); 2521 ret = drop_leaf_ref(trans, root, ref);
2522 BUG_ON(ret); 2522 BUG_ON(ret);
2523 btrfs_remove_leaf_ref(root, ref); 2523 btrfs_remove_leaf_ref(root, ref);
2524 btrfs_free_leaf_ref(ref); 2524 btrfs_free_leaf_ref(root, ref);
2525 *level = 0; 2525 *level = 0;
2526 break; 2526 break;
2527 } 2527 }
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 964ec1622d66..5368e3b6eb96 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -3497,4 +3497,3 @@ out:
3497 return ret; 3497 return ret;
3498} 3498}
3499EXPORT_SYMBOL(try_release_extent_buffer); 3499EXPORT_SYMBOL(try_release_extent_buffer);
3500
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index afe42d00b5a6..2311061f070e 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -422,4 +422,3 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
422 BUG_ON(ret); 422 BUG_ON(ret);
423 return ret; 423 return ret;
424} 424}
425
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index ded5281f8463..412ab4a26382 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1095,4 +1095,3 @@ struct file_operations btrfs_file_operations = {
1095 .compat_ioctl = btrfs_ioctl, 1095 .compat_ioctl = btrfs_ioctl,
1096#endif 1096#endif
1097}; 1097};
1098
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3aa82cec6bf7..7af8be076ee5 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -835,17 +835,17 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode)
835 struct btrfs_root *root = BTRFS_I(inode)->root; 835 struct btrfs_root *root = BTRFS_I(inode)->root;
836 int ret = 0; 836 int ret = 0;
837 837
838 spin_lock(&root->orphan_lock); 838 spin_lock(&root->list_lock);
839 839
840 /* already on the orphan list, we're good */ 840 /* already on the orphan list, we're good */
841 if (!list_empty(&BTRFS_I(inode)->i_orphan)) { 841 if (!list_empty(&BTRFS_I(inode)->i_orphan)) {
842 spin_unlock(&root->orphan_lock); 842 spin_unlock(&root->list_lock);
843 return 0; 843 return 0;
844 } 844 }
845 845
846 list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list); 846 list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list);
847 847
848 spin_unlock(&root->orphan_lock); 848 spin_unlock(&root->list_lock);
849 849
850 /* 850 /*
851 * insert an orphan item to track this unlinked/truncated file 851 * insert an orphan item to track this unlinked/truncated file
@@ -864,20 +864,20 @@ int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode)
864 struct btrfs_root *root = BTRFS_I(inode)->root; 864 struct btrfs_root *root = BTRFS_I(inode)->root;
865 int ret = 0; 865 int ret = 0;
866 866
867 spin_lock(&root->orphan_lock); 867 spin_lock(&root->list_lock);
868 868
869 if (list_empty(&BTRFS_I(inode)->i_orphan)) { 869 if (list_empty(&BTRFS_I(inode)->i_orphan)) {
870 spin_unlock(&root->orphan_lock); 870 spin_unlock(&root->list_lock);
871 return 0; 871 return 0;
872 } 872 }
873 873
874 list_del_init(&BTRFS_I(inode)->i_orphan); 874 list_del_init(&BTRFS_I(inode)->i_orphan);
875 if (!trans) { 875 if (!trans) {
876 spin_unlock(&root->orphan_lock); 876 spin_unlock(&root->list_lock);
877 return 0; 877 return 0;
878 } 878 }
879 879
880 spin_unlock(&root->orphan_lock); 880 spin_unlock(&root->list_lock);
881 881
882 ret = btrfs_del_orphan_item(trans, root, inode->i_ino); 882 ret = btrfs_del_orphan_item(trans, root, inode->i_ino);
883 883
@@ -973,9 +973,9 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
973 * add this inode to the orphan list so btrfs_orphan_del does 973 * add this inode to the orphan list so btrfs_orphan_del does
974 * the proper thing when we hit it 974 * the proper thing when we hit it
975 */ 975 */
976 spin_lock(&root->orphan_lock); 976 spin_lock(&root->list_lock);
977 list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list); 977 list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list);
978 spin_unlock(&root->orphan_lock); 978 spin_unlock(&root->list_lock);
979 979
980 /* 980 /*
981 * if this is a bad inode, means we actually succeeded in 981 * if this is a bad inode, means we actually succeeded in
@@ -3269,13 +3269,13 @@ void btrfs_destroy_inode(struct inode *inode)
3269 BTRFS_I(inode)->i_default_acl != BTRFS_ACL_NOT_CACHED) 3269 BTRFS_I(inode)->i_default_acl != BTRFS_ACL_NOT_CACHED)
3270 posix_acl_release(BTRFS_I(inode)->i_default_acl); 3270 posix_acl_release(BTRFS_I(inode)->i_default_acl);
3271 3271
3272 spin_lock(&BTRFS_I(inode)->root->orphan_lock); 3272 spin_lock(&BTRFS_I(inode)->root->list_lock);
3273 if (!list_empty(&BTRFS_I(inode)->i_orphan)) { 3273 if (!list_empty(&BTRFS_I(inode)->i_orphan)) {
3274 printk(KERN_ERR "BTRFS: inode %lu: inode still on the orphan" 3274 printk(KERN_ERR "BTRFS: inode %lu: inode still on the orphan"
3275 " list\n", inode->i_ino); 3275 " list\n", inode->i_ino);
3276 dump_stack(); 3276 dump_stack();
3277 } 3277 }
3278 spin_unlock(&BTRFS_I(inode)->root->orphan_lock); 3278 spin_unlock(&BTRFS_I(inode)->root->list_lock);
3279 3279
3280 while(1) { 3280 while(1) {
3281 ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1); 3281 ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1);
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c
index d617c29787fa..d43e14c7471a 100644
--- a/fs/btrfs/locking.c
+++ b/fs/btrfs/locking.c
@@ -56,4 +56,3 @@ int btrfs_tree_locked(struct extent_buffer *eb)
56{ 56{
57 return mutex_is_locked(&eb->mutex); 57 return mutex_is_locked(&eb->mutex);
58} 58}
59
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c
index 14d863720302..f1374d597a17 100644
--- a/fs/btrfs/print-tree.c
+++ b/fs/btrfs/print-tree.c
@@ -198,4 +198,3 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
198 free_extent_buffer(next); 198 free_extent_buffer(next);
199 } 199 }
200} 200}
201
diff --git a/fs/btrfs/ref-cache.c b/fs/btrfs/ref-cache.c
index ec9587784a3d..272b9890c982 100644
--- a/fs/btrfs/ref-cache.c
+++ b/fs/btrfs/ref-cache.c
@@ -21,12 +21,18 @@
21#include "ref-cache.h" 21#include "ref-cache.h"
22#include "transaction.h" 22#include "transaction.h"
23 23
24struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(int nr_extents) 24struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(struct btrfs_root *root,
25 int nr_extents)
25{ 26{
26 struct btrfs_leaf_ref *ref; 27 struct btrfs_leaf_ref *ref;
28 size_t size = btrfs_leaf_ref_size(nr_extents);
27 29
28 ref = kmalloc(btrfs_leaf_ref_size(nr_extents), GFP_NOFS); 30 ref = kmalloc(size, GFP_NOFS);
29 if (ref) { 31 if (ref) {
32 spin_lock(&root->fs_info->ref_cache_lock);
33 root->fs_info->total_ref_cache_size += size;
34 spin_unlock(&root->fs_info->ref_cache_lock);
35
30 memset(ref, 0, sizeof(*ref)); 36 memset(ref, 0, sizeof(*ref));
31 atomic_set(&ref->usage, 1); 37 atomic_set(&ref->usage, 1);
32 INIT_LIST_HEAD(&ref->list); 38 INIT_LIST_HEAD(&ref->list);
@@ -34,14 +40,20 @@ struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(int nr_extents)
34 return ref; 40 return ref;
35} 41}
36 42
37void btrfs_free_leaf_ref(struct btrfs_leaf_ref *ref) 43void btrfs_free_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref)
38{ 44{
39 if (!ref) 45 if (!ref)
40 return; 46 return;
41 WARN_ON(atomic_read(&ref->usage) == 0); 47 WARN_ON(atomic_read(&ref->usage) == 0);
42 if (atomic_dec_and_test(&ref->usage)) { 48 if (atomic_dec_and_test(&ref->usage)) {
49 size_t size = btrfs_leaf_ref_size(ref->nritems);
50
43 BUG_ON(ref->in_tree); 51 BUG_ON(ref->in_tree);
44 kfree(ref); 52 kfree(ref);
53
54 spin_lock(&root->fs_info->ref_cache_lock);
55 root->fs_info->total_ref_cache_size -= size;
56 spin_unlock(&root->fs_info->ref_cache_lock);
45 } 57 }
46} 58}
47 59
@@ -64,7 +76,7 @@ static struct rb_node *tree_insert(struct rb_root *root, u64 bytenr,
64 else 76 else
65 return parent; 77 return parent;
66 } 78 }
67 79
68 entry = rb_entry(node, struct btrfs_leaf_ref, rb_node); 80 entry = rb_entry(node, struct btrfs_leaf_ref, rb_node);
69 entry->in_tree = 1; 81 entry->in_tree = 1;
70 rb_link_node(node, parent, p); 82 rb_link_node(node, parent, p);
@@ -91,9 +103,8 @@ static struct rb_node *tree_search(struct rb_root *root, u64 bytenr)
91 return NULL; 103 return NULL;
92} 104}
93 105
94int btrfs_remove_leaf_refs(struct btrfs_root *root) 106int btrfs_remove_leaf_refs(struct btrfs_root *root, u64 max_root_gen)
95{ 107{
96 struct rb_node *rb;
97 struct btrfs_leaf_ref *ref = NULL; 108 struct btrfs_leaf_ref *ref = NULL;
98 struct btrfs_leaf_ref_tree *tree = root->ref_tree; 109 struct btrfs_leaf_ref_tree *tree = root->ref_tree;
99 110
@@ -101,17 +112,18 @@ int btrfs_remove_leaf_refs(struct btrfs_root *root)
101 return 0; 112 return 0;
102 113
103 spin_lock(&tree->lock); 114 spin_lock(&tree->lock);
104 while(!btrfs_leaf_ref_tree_empty(tree)) { 115 while(!list_empty(&tree->list)) {
105 rb = rb_first(&tree->root); 116 ref = list_entry(tree->list.next, struct btrfs_leaf_ref, list);
106 ref = rb_entry(rb, struct btrfs_leaf_ref, rb_node); 117 BUG_ON(!ref->in_tree);
118 if (ref->root_gen > max_root_gen)
119 break;
120
107 rb_erase(&ref->rb_node, &tree->root); 121 rb_erase(&ref->rb_node, &tree->root);
108 ref->in_tree = 0; 122 ref->in_tree = 0;
109 list_del_init(&ref->list); 123 list_del_init(&ref->list);
110 124
111 spin_unlock(&tree->lock); 125 spin_unlock(&tree->lock);
112 126 btrfs_free_leaf_ref(root, ref);
113 btrfs_free_leaf_ref(ref);
114
115 cond_resched(); 127 cond_resched();
116 spin_lock(&tree->lock); 128 spin_lock(&tree->lock);
117 } 129 }
@@ -143,7 +155,6 @@ int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref)
143{ 155{
144 int ret = 0; 156 int ret = 0;
145 struct rb_node *rb; 157 struct rb_node *rb;
146 size_t size = btrfs_leaf_ref_size(ref->nritems);
147 struct btrfs_leaf_ref_tree *tree = root->ref_tree; 158 struct btrfs_leaf_ref_tree *tree = root->ref_tree;
148 159
149 spin_lock(&tree->lock); 160 spin_lock(&tree->lock);
@@ -151,9 +162,6 @@ int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref)
151 if (rb) { 162 if (rb) {
152 ret = -EEXIST; 163 ret = -EEXIST;
153 } else { 164 } else {
154 spin_lock(&root->fs_info->ref_cache_lock);
155 root->fs_info->total_ref_cache_size += size;
156 spin_unlock(&root->fs_info->ref_cache_lock);
157 atomic_inc(&ref->usage); 165 atomic_inc(&ref->usage);
158 list_add_tail(&ref->list, &tree->list); 166 list_add_tail(&ref->list, &tree->list);
159 } 167 }
@@ -163,15 +171,10 @@ int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref)
163 171
164int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref) 172int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref)
165{ 173{
166 size_t size = btrfs_leaf_ref_size(ref->nritems);
167 struct btrfs_leaf_ref_tree *tree = root->ref_tree; 174 struct btrfs_leaf_ref_tree *tree = root->ref_tree;
168 175
169 BUG_ON(!ref->in_tree); 176 BUG_ON(!ref->in_tree);
170 spin_lock(&tree->lock); 177 spin_lock(&tree->lock);
171
172 spin_lock(&root->fs_info->ref_cache_lock);
173 root->fs_info->total_ref_cache_size -= size;
174 spin_unlock(&root->fs_info->ref_cache_lock);
175 178
176 rb_erase(&ref->rb_node, &tree->root); 179 rb_erase(&ref->rb_node, &tree->root);
177 ref->in_tree = 0; 180 ref->in_tree = 0;
@@ -179,7 +182,6 @@ int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref)
179 182
180 spin_unlock(&tree->lock); 183 spin_unlock(&tree->lock);
181 184
182 btrfs_free_leaf_ref(ref); 185 btrfs_free_leaf_ref(root, ref);
183 return 0; 186 return 0;
184} 187}
185
diff --git a/fs/btrfs/ref-cache.h b/fs/btrfs/ref-cache.h
index 823c049f72f1..c361b321c0c3 100644
--- a/fs/btrfs/ref-cache.h
+++ b/fs/btrfs/ref-cache.h
@@ -30,6 +30,7 @@ struct btrfs_leaf_ref {
30 int in_tree; 30 int in_tree;
31 atomic_t usage; 31 atomic_t usage;
32 32
33 u64 root_gen;
33 u64 bytenr; 34 u64 bytenr;
34 u64 owner; 35 u64 owner;
35 u64 generation; 36 u64 generation;
@@ -41,14 +42,13 @@ struct btrfs_leaf_ref {
41 42
42static inline size_t btrfs_leaf_ref_size(int nr_extents) 43static inline size_t btrfs_leaf_ref_size(int nr_extents)
43{ 44{
44 return sizeof(struct btrfs_leaf_ref) + 45 return sizeof(struct btrfs_leaf_ref) +
45 sizeof(struct btrfs_extent_info) * nr_extents; 46 sizeof(struct btrfs_extent_info) * nr_extents;
46} 47}
47 48
48static inline void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree) 49static inline void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree)
49{ 50{
50 tree->root.rb_node = NULL; 51 tree->root.rb_node = NULL;
51 tree->last = NULL;
52 INIT_LIST_HEAD(&tree->list); 52 INIT_LIST_HEAD(&tree->list);
53 spin_lock_init(&tree->lock); 53 spin_lock_init(&tree->lock);
54} 54}
@@ -59,12 +59,13 @@ static inline int btrfs_leaf_ref_tree_empty(struct btrfs_leaf_ref_tree *tree)
59} 59}
60 60
61void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree); 61void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree);
62struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(int nr_extents); 62struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(struct btrfs_root *root,
63void btrfs_free_leaf_ref(struct btrfs_leaf_ref *ref); 63 int nr_extents);
64void btrfs_free_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref);
64struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root, 65struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root,
65 u64 bytenr); 66 u64 bytenr);
66int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref); 67int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref);
67int btrfs_remove_leaf_refs(struct btrfs_root *root); 68int btrfs_remove_leaf_refs(struct btrfs_root *root, u64 max_root_gen);
68int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref); 69int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref);
69 70
70#endif 71#endif
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 216f31571620..52c5524896a3 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -98,20 +98,24 @@ static noinline int record_root_in_trans(struct btrfs_root *root)
98 BUG_ON(!dirty); 98 BUG_ON(!dirty);
99 dirty->root = kmalloc(sizeof(*dirty->root), GFP_NOFS); 99 dirty->root = kmalloc(sizeof(*dirty->root), GFP_NOFS);
100 BUG_ON(!dirty->root); 100 BUG_ON(!dirty->root);
101
102 dirty->latest_root = root; 101 dirty->latest_root = root;
103 INIT_LIST_HEAD(&dirty->list); 102 INIT_LIST_HEAD(&dirty->list);
104 103
105 root->commit_root = btrfs_root_node(root); 104 root->commit_root = btrfs_root_node(root);
106 root->dirty_root = dirty;
107 105
108 memcpy(dirty->root, root, sizeof(*root)); 106 memcpy(dirty->root, root, sizeof(*root));
109 dirty->root->ref_tree = &root->ref_tree_struct;
110
111 spin_lock_init(&dirty->root->node_lock); 107 spin_lock_init(&dirty->root->node_lock);
108 spin_lock_init(&dirty->root->list_lock);
112 mutex_init(&dirty->root->objectid_mutex); 109 mutex_init(&dirty->root->objectid_mutex);
110 INIT_LIST_HEAD(&dirty->root->dead_list);
113 dirty->root->node = root->commit_root; 111 dirty->root->node = root->commit_root;
114 dirty->root->commit_root = NULL; 112 dirty->root->commit_root = NULL;
113
114 spin_lock(&root->list_lock);
115 list_add(&dirty->root->dead_list, &root->dead_list);
116 spin_unlock(&root->list_lock);
117
118 root->dirty_root = dirty;
115 } else { 119 } else {
116 WARN_ON(1); 120 WARN_ON(1);
117 } 121 }
@@ -356,8 +360,6 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
356 list_del_init(next); 360 list_del_init(next);
357 root = list_entry(next, struct btrfs_root, dirty_list); 361 root = list_entry(next, struct btrfs_root, dirty_list);
358 update_cowonly_root(trans, root); 362 update_cowonly_root(trans, root);
359 if (root->fs_info->closing)
360 btrfs_remove_leaf_refs(root);
361 } 363 }
362 return 0; 364 return 0;
363} 365}
@@ -410,7 +412,11 @@ static noinline int add_dirty_roots(struct btrfs_trans_handle *trans,
410 412
411 free_extent_buffer(root->commit_root); 413 free_extent_buffer(root->commit_root);
412 root->commit_root = NULL; 414 root->commit_root = NULL;
413 415
416 spin_lock(&root->list_lock);
417 list_del_init(&dirty->root->dead_list);
418 spin_unlock(&root->list_lock);
419
414 kfree(dirty->root); 420 kfree(dirty->root);
415 kfree(dirty); 421 kfree(dirty);
416 422
@@ -497,6 +503,7 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
497 unsigned long nr; 503 unsigned long nr;
498 u64 num_bytes; 504 u64 num_bytes;
499 u64 bytes_used; 505 u64 bytes_used;
506 u64 max_useless;
500 int ret = 0; 507 int ret = 0;
501 int err; 508 int err;
502 509
@@ -554,10 +561,25 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
554 } 561 }
555 mutex_unlock(&root->fs_info->drop_mutex); 562 mutex_unlock(&root->fs_info->drop_mutex);
556 563
564 spin_lock(&root->list_lock);
565 list_del_init(&dirty->root->dead_list);
566 if (!list_empty(&root->dead_list)) {
567 struct btrfs_root *oldest;
568 oldest = list_entry(root->dead_list.prev,
569 struct btrfs_root, dead_list);
570 max_useless = oldest->root_key.offset - 1;
571 } else {
572 max_useless = root->root_key.offset - 1;
573 }
574 spin_unlock(&root->list_lock);
575
557 nr = trans->blocks_used; 576 nr = trans->blocks_used;
558 ret = btrfs_end_transaction(trans, tree_root); 577 ret = btrfs_end_transaction(trans, tree_root);
559 BUG_ON(ret); 578 BUG_ON(ret);
560 579
580 ret = btrfs_remove_leaf_refs(root, max_useless);
581 BUG_ON(ret);
582
561 free_extent_buffer(dirty->root->node); 583 free_extent_buffer(dirty->root->node);
562 kfree(dirty->root); 584 kfree(dirty->root);
563 kfree(dirty); 585 kfree(dirty);
@@ -785,10 +807,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
785 put_transaction(cur_trans); 807 put_transaction(cur_trans);
786 put_transaction(cur_trans); 808 put_transaction(cur_trans);
787 809
810 list_splice_init(&dirty_fs_roots, &root->fs_info->dead_roots);
788 if (root->fs_info->closing) 811 if (root->fs_info->closing)
789 list_splice_init(&root->fs_info->dead_roots, &dirty_fs_roots); 812 list_splice_init(&root->fs_info->dead_roots, &dirty_fs_roots);
790 else
791 list_splice_init(&dirty_fs_roots, &root->fs_info->dead_roots);
792 813
793 mutex_unlock(&root->fs_info->trans_mutex); 814 mutex_unlock(&root->fs_info->trans_mutex);
794 kmem_cache_free(btrfs_trans_handle_cachep, trans); 815 kmem_cache_free(btrfs_trans_handle_cachep, trans);
@@ -814,4 +835,3 @@ again:
814 } 835 }
815 return 0; 836 return 0;
816} 837}
817
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 5e6ee7a6f738..18db4cbe2794 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2527,4 +2527,3 @@ again:
2527error: 2527error:
2528 return ret; 2528 return ret;
2529} 2529}
2530