diff options
author | Arne Jansen <sensille@gmx.net> | 2011-09-12 09:26:38 -0400 |
---|---|---|
committer | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2011-12-22 10:22:27 -0500 |
commit | 66d7e7f09f77456fe68683247d77721032a00ee5 (patch) | |
tree | bbf7df3933ed47aa202d60d835864543d25df82d /fs/btrfs/extent-tree.c | |
parent | c7d22a3c3cdb73d8a0151e2ccc8cf4a48c48310b (diff) |
Btrfs: mark delayed refs as for cow
Add a for_cow parameter to add_delayed_*_ref and pass the appropriate value
from every call site. The for_cow parameter will later on be used to
determine if a ref will change anything with respect to qgroups.
Delayed refs coming from relocation are always counted as for_cow, as they
don't change subvol quota.
Also pass in the fs_info for later use.
btrfs_find_all_roots() will use this as an optimization, as changes that are
for_cow will not change anything with respect to which root points to a
certain leaf. Thus, we don't need to add the current sequence number to
those delayed refs.
Signed-off-by: Arne Jansen <sensille@gmx.net>
Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 101 |
1 files changed, 60 insertions, 41 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 813c6bb96c9a..dc8b9a834596 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1872,20 +1872,24 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, | |||
1872 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | 1872 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, |
1873 | struct btrfs_root *root, | 1873 | struct btrfs_root *root, |
1874 | u64 bytenr, u64 num_bytes, u64 parent, | 1874 | u64 bytenr, u64 num_bytes, u64 parent, |
1875 | u64 root_objectid, u64 owner, u64 offset) | 1875 | u64 root_objectid, u64 owner, u64 offset, int for_cow) |
1876 | { | 1876 | { |
1877 | int ret; | 1877 | int ret; |
1878 | struct btrfs_fs_info *fs_info = root->fs_info; | ||
1879 | |||
1878 | BUG_ON(owner < BTRFS_FIRST_FREE_OBJECTID && | 1880 | BUG_ON(owner < BTRFS_FIRST_FREE_OBJECTID && |
1879 | root_objectid == BTRFS_TREE_LOG_OBJECTID); | 1881 | root_objectid == BTRFS_TREE_LOG_OBJECTID); |
1880 | 1882 | ||
1881 | if (owner < BTRFS_FIRST_FREE_OBJECTID) { | 1883 | if (owner < BTRFS_FIRST_FREE_OBJECTID) { |
1882 | ret = btrfs_add_delayed_tree_ref(trans, bytenr, num_bytes, | 1884 | ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr, |
1885 | num_bytes, | ||
1883 | parent, root_objectid, (int)owner, | 1886 | parent, root_objectid, (int)owner, |
1884 | BTRFS_ADD_DELAYED_REF, NULL); | 1887 | BTRFS_ADD_DELAYED_REF, NULL, for_cow); |
1885 | } else { | 1888 | } else { |
1886 | ret = btrfs_add_delayed_data_ref(trans, bytenr, num_bytes, | 1889 | ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr, |
1890 | num_bytes, | ||
1887 | parent, root_objectid, owner, offset, | 1891 | parent, root_objectid, owner, offset, |
1888 | BTRFS_ADD_DELAYED_REF, NULL); | 1892 | BTRFS_ADD_DELAYED_REF, NULL, for_cow); |
1889 | } | 1893 | } |
1890 | return ret; | 1894 | return ret; |
1891 | } | 1895 | } |
@@ -2405,7 +2409,8 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, | |||
2405 | extent_op->update_key = 0; | 2409 | extent_op->update_key = 0; |
2406 | extent_op->is_data = is_data ? 1 : 0; | 2410 | extent_op->is_data = is_data ? 1 : 0; |
2407 | 2411 | ||
2408 | ret = btrfs_add_delayed_extent_op(trans, bytenr, num_bytes, extent_op); | 2412 | ret = btrfs_add_delayed_extent_op(root->fs_info, trans, bytenr, |
2413 | num_bytes, extent_op); | ||
2409 | if (ret) | 2414 | if (ret) |
2410 | kfree(extent_op); | 2415 | kfree(extent_op); |
2411 | return ret; | 2416 | return ret; |
@@ -2590,7 +2595,7 @@ out: | |||
2590 | static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, | 2595 | static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, |
2591 | struct btrfs_root *root, | 2596 | struct btrfs_root *root, |
2592 | struct extent_buffer *buf, | 2597 | struct extent_buffer *buf, |
2593 | int full_backref, int inc) | 2598 | int full_backref, int inc, int for_cow) |
2594 | { | 2599 | { |
2595 | u64 bytenr; | 2600 | u64 bytenr; |
2596 | u64 num_bytes; | 2601 | u64 num_bytes; |
@@ -2603,7 +2608,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, | |||
2603 | int level; | 2608 | int level; |
2604 | int ret = 0; | 2609 | int ret = 0; |
2605 | int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *, | 2610 | int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *, |
2606 | u64, u64, u64, u64, u64, u64); | 2611 | u64, u64, u64, u64, u64, u64, int); |
2607 | 2612 | ||
2608 | ref_root = btrfs_header_owner(buf); | 2613 | ref_root = btrfs_header_owner(buf); |
2609 | nritems = btrfs_header_nritems(buf); | 2614 | nritems = btrfs_header_nritems(buf); |
@@ -2640,14 +2645,15 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, | |||
2640 | key.offset -= btrfs_file_extent_offset(buf, fi); | 2645 | key.offset -= btrfs_file_extent_offset(buf, fi); |
2641 | ret = process_func(trans, root, bytenr, num_bytes, | 2646 | ret = process_func(trans, root, bytenr, num_bytes, |
2642 | parent, ref_root, key.objectid, | 2647 | parent, ref_root, key.objectid, |
2643 | key.offset); | 2648 | key.offset, for_cow); |
2644 | if (ret) | 2649 | if (ret) |
2645 | goto fail; | 2650 | goto fail; |
2646 | } else { | 2651 | } else { |
2647 | bytenr = btrfs_node_blockptr(buf, i); | 2652 | bytenr = btrfs_node_blockptr(buf, i); |
2648 | num_bytes = btrfs_level_size(root, level - 1); | 2653 | num_bytes = btrfs_level_size(root, level - 1); |
2649 | ret = process_func(trans, root, bytenr, num_bytes, | 2654 | ret = process_func(trans, root, bytenr, num_bytes, |
2650 | parent, ref_root, level - 1, 0); | 2655 | parent, ref_root, level - 1, 0, |
2656 | for_cow); | ||
2651 | if (ret) | 2657 | if (ret) |
2652 | goto fail; | 2658 | goto fail; |
2653 | } | 2659 | } |
@@ -2659,15 +2665,15 @@ fail: | |||
2659 | } | 2665 | } |
2660 | 2666 | ||
2661 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 2667 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
2662 | struct extent_buffer *buf, int full_backref) | 2668 | struct extent_buffer *buf, int full_backref, int for_cow) |
2663 | { | 2669 | { |
2664 | return __btrfs_mod_ref(trans, root, buf, full_backref, 1); | 2670 | return __btrfs_mod_ref(trans, root, buf, full_backref, 1, for_cow); |
2665 | } | 2671 | } |
2666 | 2672 | ||
2667 | int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 2673 | int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
2668 | struct extent_buffer *buf, int full_backref) | 2674 | struct extent_buffer *buf, int full_backref, int for_cow) |
2669 | { | 2675 | { |
2670 | return __btrfs_mod_ref(trans, root, buf, full_backref, 0); | 2676 | return __btrfs_mod_ref(trans, root, buf, full_backref, 0, for_cow); |
2671 | } | 2677 | } |
2672 | 2678 | ||
2673 | static int write_one_cache_group(struct btrfs_trans_handle *trans, | 2679 | static int write_one_cache_group(struct btrfs_trans_handle *trans, |
@@ -4937,16 +4943,17 @@ out: | |||
4937 | void btrfs_free_tree_block(struct btrfs_trans_handle *trans, | 4943 | void btrfs_free_tree_block(struct btrfs_trans_handle *trans, |
4938 | struct btrfs_root *root, | 4944 | struct btrfs_root *root, |
4939 | struct extent_buffer *buf, | 4945 | struct extent_buffer *buf, |
4940 | u64 parent, int last_ref) | 4946 | u64 parent, int last_ref, int for_cow) |
4941 | { | 4947 | { |
4942 | struct btrfs_block_group_cache *cache = NULL; | 4948 | struct btrfs_block_group_cache *cache = NULL; |
4943 | int ret; | 4949 | int ret; |
4944 | 4950 | ||
4945 | if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) { | 4951 | if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) { |
4946 | ret = btrfs_add_delayed_tree_ref(trans, buf->start, buf->len, | 4952 | ret = btrfs_add_delayed_tree_ref(root->fs_info, trans, |
4947 | parent, root->root_key.objectid, | 4953 | buf->start, buf->len, |
4948 | btrfs_header_level(buf), | 4954 | parent, root->root_key.objectid, |
4949 | BTRFS_DROP_DELAYED_REF, NULL); | 4955 | btrfs_header_level(buf), |
4956 | BTRFS_DROP_DELAYED_REF, NULL, for_cow); | ||
4950 | BUG_ON(ret); | 4957 | BUG_ON(ret); |
4951 | } | 4958 | } |
4952 | 4959 | ||
@@ -4981,12 +4988,12 @@ out: | |||
4981 | btrfs_put_block_group(cache); | 4988 | btrfs_put_block_group(cache); |
4982 | } | 4989 | } |
4983 | 4990 | ||
4984 | int btrfs_free_extent(struct btrfs_trans_handle *trans, | 4991 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
4985 | struct btrfs_root *root, | 4992 | u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, |
4986 | u64 bytenr, u64 num_bytes, u64 parent, | 4993 | u64 owner, u64 offset, int for_cow) |
4987 | u64 root_objectid, u64 owner, u64 offset) | ||
4988 | { | 4994 | { |
4989 | int ret; | 4995 | int ret; |
4996 | struct btrfs_fs_info *fs_info = root->fs_info; | ||
4990 | 4997 | ||
4991 | /* | 4998 | /* |
4992 | * tree log blocks never actually go into the extent allocation | 4999 | * tree log blocks never actually go into the extent allocation |
@@ -4998,14 +5005,17 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
4998 | btrfs_pin_extent(root, bytenr, num_bytes, 1); | 5005 | btrfs_pin_extent(root, bytenr, num_bytes, 1); |
4999 | ret = 0; | 5006 | ret = 0; |
5000 | } else if (owner < BTRFS_FIRST_FREE_OBJECTID) { | 5007 | } else if (owner < BTRFS_FIRST_FREE_OBJECTID) { |
5001 | ret = btrfs_add_delayed_tree_ref(trans, bytenr, num_bytes, | 5008 | ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr, |
5009 | num_bytes, | ||
5002 | parent, root_objectid, (int)owner, | 5010 | parent, root_objectid, (int)owner, |
5003 | BTRFS_DROP_DELAYED_REF, NULL); | 5011 | BTRFS_DROP_DELAYED_REF, NULL, for_cow); |
5004 | BUG_ON(ret); | 5012 | BUG_ON(ret); |
5005 | } else { | 5013 | } else { |
5006 | ret = btrfs_add_delayed_data_ref(trans, bytenr, num_bytes, | 5014 | ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr, |
5007 | parent, root_objectid, owner, | 5015 | num_bytes, |
5008 | offset, BTRFS_DROP_DELAYED_REF, NULL); | 5016 | parent, root_objectid, owner, |
5017 | offset, BTRFS_DROP_DELAYED_REF, | ||
5018 | NULL, for_cow); | ||
5009 | BUG_ON(ret); | 5019 | BUG_ON(ret); |
5010 | } | 5020 | } |
5011 | return ret; | 5021 | return ret; |
@@ -5826,9 +5836,10 @@ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans, | |||
5826 | 5836 | ||
5827 | BUG_ON(root_objectid == BTRFS_TREE_LOG_OBJECTID); | 5837 | BUG_ON(root_objectid == BTRFS_TREE_LOG_OBJECTID); |
5828 | 5838 | ||
5829 | ret = btrfs_add_delayed_data_ref(trans, ins->objectid, ins->offset, | 5839 | ret = btrfs_add_delayed_data_ref(root->fs_info, trans, ins->objectid, |
5830 | 0, root_objectid, owner, offset, | 5840 | ins->offset, 0, |
5831 | BTRFS_ADD_DELAYED_EXTENT, NULL); | 5841 | root_objectid, owner, offset, |
5842 | BTRFS_ADD_DELAYED_EXTENT, NULL, 0); | ||
5832 | return ret; | 5843 | return ret; |
5833 | } | 5844 | } |
5834 | 5845 | ||
@@ -5998,7 +6009,7 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
5998 | struct btrfs_root *root, u32 blocksize, | 6009 | struct btrfs_root *root, u32 blocksize, |
5999 | u64 parent, u64 root_objectid, | 6010 | u64 parent, u64 root_objectid, |
6000 | struct btrfs_disk_key *key, int level, | 6011 | struct btrfs_disk_key *key, int level, |
6001 | u64 hint, u64 empty_size) | 6012 | u64 hint, u64 empty_size, int for_cow) |
6002 | { | 6013 | { |
6003 | struct btrfs_key ins; | 6014 | struct btrfs_key ins; |
6004 | struct btrfs_block_rsv *block_rsv; | 6015 | struct btrfs_block_rsv *block_rsv; |
@@ -6042,10 +6053,11 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
6042 | extent_op->update_flags = 1; | 6053 | extent_op->update_flags = 1; |
6043 | extent_op->is_data = 0; | 6054 | extent_op->is_data = 0; |
6044 | 6055 | ||
6045 | ret = btrfs_add_delayed_tree_ref(trans, ins.objectid, | 6056 | ret = btrfs_add_delayed_tree_ref(root->fs_info, trans, |
6057 | ins.objectid, | ||
6046 | ins.offset, parent, root_objectid, | 6058 | ins.offset, parent, root_objectid, |
6047 | level, BTRFS_ADD_DELAYED_EXTENT, | 6059 | level, BTRFS_ADD_DELAYED_EXTENT, |
6048 | extent_op); | 6060 | extent_op, for_cow); |
6049 | BUG_ON(ret); | 6061 | BUG_ON(ret); |
6050 | } | 6062 | } |
6051 | return buf; | 6063 | return buf; |
@@ -6062,6 +6074,7 @@ struct walk_control { | |||
6062 | int keep_locks; | 6074 | int keep_locks; |
6063 | int reada_slot; | 6075 | int reada_slot; |
6064 | int reada_count; | 6076 | int reada_count; |
6077 | int for_reloc; | ||
6065 | }; | 6078 | }; |
6066 | 6079 | ||
6067 | #define DROP_REFERENCE 1 | 6080 | #define DROP_REFERENCE 1 |
@@ -6200,9 +6213,9 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans, | |||
6200 | /* wc->stage == UPDATE_BACKREF */ | 6213 | /* wc->stage == UPDATE_BACKREF */ |
6201 | if (!(wc->flags[level] & flag)) { | 6214 | if (!(wc->flags[level] & flag)) { |
6202 | BUG_ON(!path->locks[level]); | 6215 | BUG_ON(!path->locks[level]); |
6203 | ret = btrfs_inc_ref(trans, root, eb, 1); | 6216 | ret = btrfs_inc_ref(trans, root, eb, 1, wc->for_reloc); |
6204 | BUG_ON(ret); | 6217 | BUG_ON(ret); |
6205 | ret = btrfs_dec_ref(trans, root, eb, 0); | 6218 | ret = btrfs_dec_ref(trans, root, eb, 0, wc->for_reloc); |
6206 | BUG_ON(ret); | 6219 | BUG_ON(ret); |
6207 | ret = btrfs_set_disk_extent_flags(trans, root, eb->start, | 6220 | ret = btrfs_set_disk_extent_flags(trans, root, eb->start, |
6208 | eb->len, flag, 0); | 6221 | eb->len, flag, 0); |
@@ -6346,7 +6359,7 @@ skip: | |||
6346 | } | 6359 | } |
6347 | 6360 | ||
6348 | ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent, | 6361 | ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent, |
6349 | root->root_key.objectid, level - 1, 0); | 6362 | root->root_key.objectid, level - 1, 0, 0); |
6350 | BUG_ON(ret); | 6363 | BUG_ON(ret); |
6351 | } | 6364 | } |
6352 | btrfs_tree_unlock(next); | 6365 | btrfs_tree_unlock(next); |
@@ -6420,9 +6433,11 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans, | |||
6420 | if (wc->refs[level] == 1) { | 6433 | if (wc->refs[level] == 1) { |
6421 | if (level == 0) { | 6434 | if (level == 0) { |
6422 | if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) | 6435 | if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) |
6423 | ret = btrfs_dec_ref(trans, root, eb, 1); | 6436 | ret = btrfs_dec_ref(trans, root, eb, 1, |
6437 | wc->for_reloc); | ||
6424 | else | 6438 | else |
6425 | ret = btrfs_dec_ref(trans, root, eb, 0); | 6439 | ret = btrfs_dec_ref(trans, root, eb, 0, |
6440 | wc->for_reloc); | ||
6426 | BUG_ON(ret); | 6441 | BUG_ON(ret); |
6427 | } | 6442 | } |
6428 | /* make block locked assertion in clean_tree_block happy */ | 6443 | /* make block locked assertion in clean_tree_block happy */ |
@@ -6449,7 +6464,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans, | |||
6449 | btrfs_header_owner(path->nodes[level + 1])); | 6464 | btrfs_header_owner(path->nodes[level + 1])); |
6450 | } | 6465 | } |
6451 | 6466 | ||
6452 | btrfs_free_tree_block(trans, root, eb, parent, wc->refs[level] == 1); | 6467 | btrfs_free_tree_block(trans, root, eb, parent, wc->refs[level] == 1, 0); |
6453 | out: | 6468 | out: |
6454 | wc->refs[level] = 0; | 6469 | wc->refs[level] = 0; |
6455 | wc->flags[level] = 0; | 6470 | wc->flags[level] = 0; |
@@ -6533,7 +6548,8 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans, | |||
6533 | * blocks are properly updated. | 6548 | * blocks are properly updated. |
6534 | */ | 6549 | */ |
6535 | void btrfs_drop_snapshot(struct btrfs_root *root, | 6550 | void btrfs_drop_snapshot(struct btrfs_root *root, |
6536 | struct btrfs_block_rsv *block_rsv, int update_ref) | 6551 | struct btrfs_block_rsv *block_rsv, int update_ref, |
6552 | int for_reloc) | ||
6537 | { | 6553 | { |
6538 | struct btrfs_path *path; | 6554 | struct btrfs_path *path; |
6539 | struct btrfs_trans_handle *trans; | 6555 | struct btrfs_trans_handle *trans; |
@@ -6621,6 +6637,7 @@ void btrfs_drop_snapshot(struct btrfs_root *root, | |||
6621 | wc->stage = DROP_REFERENCE; | 6637 | wc->stage = DROP_REFERENCE; |
6622 | wc->update_ref = update_ref; | 6638 | wc->update_ref = update_ref; |
6623 | wc->keep_locks = 0; | 6639 | wc->keep_locks = 0; |
6640 | wc->for_reloc = for_reloc; | ||
6624 | wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root); | 6641 | wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root); |
6625 | 6642 | ||
6626 | while (1) { | 6643 | while (1) { |
@@ -6705,6 +6722,7 @@ out: | |||
6705 | * drop subtree rooted at tree block 'node'. | 6722 | * drop subtree rooted at tree block 'node'. |
6706 | * | 6723 | * |
6707 | * NOTE: this function will unlock and release tree block 'node' | 6724 | * NOTE: this function will unlock and release tree block 'node' |
6725 | * only used by relocation code | ||
6708 | */ | 6726 | */ |
6709 | int btrfs_drop_subtree(struct btrfs_trans_handle *trans, | 6727 | int btrfs_drop_subtree(struct btrfs_trans_handle *trans, |
6710 | struct btrfs_root *root, | 6728 | struct btrfs_root *root, |
@@ -6749,6 +6767,7 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, | |||
6749 | wc->stage = DROP_REFERENCE; | 6767 | wc->stage = DROP_REFERENCE; |
6750 | wc->update_ref = 0; | 6768 | wc->update_ref = 0; |
6751 | wc->keep_locks = 1; | 6769 | wc->keep_locks = 1; |
6770 | wc->for_reloc = 1; | ||
6752 | wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root); | 6771 | wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root); |
6753 | 6772 | ||
6754 | while (1) { | 6773 | while (1) { |