diff options
Diffstat (limited to 'fs')
| -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 245eb00435d..c4792062dd5 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 83422088c62..be16cd49ef6 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 eb4dd3d75cf..125094617fe 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 ec1ba8ddb35..e826730d750 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 fe1ddbd2bfd..37ca8df30c3 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 964ec1622d6..5368e3b6eb9 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 afe42d00b5a..2311061f070 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 ded5281f846..412ab4a2638 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 3aa82cec6bf..7af8be076ee 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 d617c29787f..d43e14c7471 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 14d86372030..f1374d597a1 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 ec9587784a3..272b9890c98 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 823c049f72f..c361b321c0c 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 216f3157162..52c5524896a 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 5e6ee7a6f73..18db4cbe279 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 | |||
