diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.c | 1 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 1 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 5 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 18 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 1 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 1 | ||||
-rw-r--r-- | fs/btrfs/file.c | 1 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 22 | ||||
-rw-r--r-- | fs/btrfs/locking.c | 1 | ||||
-rw-r--r-- | fs/btrfs/print-tree.c | 1 | ||||
-rw-r--r-- | fs/btrfs/ref-cache.c | 48 | ||||
-rw-r--r-- | fs/btrfs/ref-cache.h | 11 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 40 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 1 |
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 | } |
1090 | out: | 1090 | out: |
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 | ||
2318 | static int noinline drop_leaf_ref_no_cache(struct btrfs_trans_handle *trans, | 2318 | static 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 | ||
2369 | static int noinline drop_leaf_ref(struct btrfs_trans_handle *trans, | 2369 | static 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 | } |
3499 | EXPORT_SYMBOL(try_release_extent_buffer); | 3499 | EXPORT_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 | ||
24 | struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(int nr_extents) | 24 | struct 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 | ||
37 | void btrfs_free_leaf_ref(struct btrfs_leaf_ref *ref) | 43 | void 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 | ||
94 | int btrfs_remove_leaf_refs(struct btrfs_root *root) | 106 | int 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 | ||
164 | int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref) | 172 | int 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 | ||
42 | static inline size_t btrfs_leaf_ref_size(int nr_extents) | 43 | static 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 | ||
48 | static inline void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree) | 49 | static 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 | ||
61 | void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree); | 61 | void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree); |
62 | struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(int nr_extents); | 62 | struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(struct btrfs_root *root, |
63 | void btrfs_free_leaf_ref(struct btrfs_leaf_ref *ref); | 63 | int nr_extents); |
64 | void btrfs_free_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref); | ||
64 | struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root, | 65 | struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root, |
65 | u64 bytenr); | 66 | u64 bytenr); |
66 | int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref); | 67 | int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref); |
67 | int btrfs_remove_leaf_refs(struct btrfs_root *root); | 68 | int btrfs_remove_leaf_refs(struct btrfs_root *root, u64 max_root_gen); |
68 | int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref); | 69 | int 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: | |||
2527 | error: | 2527 | error: |
2528 | return ret; | 2528 | return ret; |
2529 | } | 2529 | } |
2530 | |||