diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 72 |
1 files changed, 47 insertions, 25 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 94627c4cc193..56e50137d0e6 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -195,6 +195,14 @@ static int exclude_super_stripes(struct btrfs_root *root, | |||
195 | int stripe_len; | 195 | int stripe_len; |
196 | int i, nr, ret; | 196 | int i, nr, ret; |
197 | 197 | ||
198 | if (cache->key.objectid < BTRFS_SUPER_INFO_OFFSET) { | ||
199 | stripe_len = BTRFS_SUPER_INFO_OFFSET - cache->key.objectid; | ||
200 | cache->bytes_super += stripe_len; | ||
201 | ret = add_excluded_extent(root, cache->key.objectid, | ||
202 | stripe_len); | ||
203 | BUG_ON(ret); | ||
204 | } | ||
205 | |||
198 | for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { | 206 | for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { |
199 | bytenr = btrfs_sb_offset(i); | 207 | bytenr = btrfs_sb_offset(i); |
200 | ret = btrfs_rmap_block(&root->fs_info->mapping_tree, | 208 | ret = btrfs_rmap_block(&root->fs_info->mapping_tree, |
@@ -255,7 +263,7 @@ static u64 add_new_free_space(struct btrfs_block_group_cache *block_group, | |||
255 | if (ret) | 263 | if (ret) |
256 | break; | 264 | break; |
257 | 265 | ||
258 | if (extent_start == start) { | 266 | if (extent_start <= start) { |
259 | start = extent_end + 1; | 267 | start = extent_end + 1; |
260 | } else if (extent_start > start && extent_start < end) { | 268 | } else if (extent_start > start && extent_start < end) { |
261 | size = extent_start - start; | 269 | size = extent_start - start; |
@@ -2880,9 +2888,9 @@ static noinline void flush_delalloc_async(struct btrfs_work *work) | |||
2880 | root = async->root; | 2888 | root = async->root; |
2881 | info = async->info; | 2889 | info = async->info; |
2882 | 2890 | ||
2883 | btrfs_start_delalloc_inodes(root); | 2891 | btrfs_start_delalloc_inodes(root, 0); |
2884 | wake_up(&info->flush_wait); | 2892 | wake_up(&info->flush_wait); |
2885 | btrfs_wait_ordered_extents(root, 0); | 2893 | btrfs_wait_ordered_extents(root, 0, 0); |
2886 | 2894 | ||
2887 | spin_lock(&info->lock); | 2895 | spin_lock(&info->lock); |
2888 | info->flushing = 0; | 2896 | info->flushing = 0; |
@@ -2956,8 +2964,8 @@ static void flush_delalloc(struct btrfs_root *root, | |||
2956 | return; | 2964 | return; |
2957 | 2965 | ||
2958 | flush: | 2966 | flush: |
2959 | btrfs_start_delalloc_inodes(root); | 2967 | btrfs_start_delalloc_inodes(root, 0); |
2960 | btrfs_wait_ordered_extents(root, 0); | 2968 | btrfs_wait_ordered_extents(root, 0, 0); |
2961 | 2969 | ||
2962 | spin_lock(&info->lock); | 2970 | spin_lock(&info->lock); |
2963 | info->flushing = 0; | 2971 | info->flushing = 0; |
@@ -3454,14 +3462,6 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
3454 | else | 3462 | else |
3455 | old_val -= num_bytes; | 3463 | old_val -= num_bytes; |
3456 | btrfs_set_super_bytes_used(&info->super_copy, old_val); | 3464 | btrfs_set_super_bytes_used(&info->super_copy, old_val); |
3457 | |||
3458 | /* block accounting for root item */ | ||
3459 | old_val = btrfs_root_used(&root->root_item); | ||
3460 | if (alloc) | ||
3461 | old_val += num_bytes; | ||
3462 | else | ||
3463 | old_val -= num_bytes; | ||
3464 | btrfs_set_root_used(&root->root_item, old_val); | ||
3465 | spin_unlock(&info->delalloc_lock); | 3465 | spin_unlock(&info->delalloc_lock); |
3466 | 3466 | ||
3467 | while (total) { | 3467 | while (total) { |
@@ -4049,6 +4049,21 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
4049 | return ret; | 4049 | return ret; |
4050 | } | 4050 | } |
4051 | 4051 | ||
4052 | int btrfs_free_tree_block(struct btrfs_trans_handle *trans, | ||
4053 | struct btrfs_root *root, | ||
4054 | u64 bytenr, u32 blocksize, | ||
4055 | u64 parent, u64 root_objectid, int level) | ||
4056 | { | ||
4057 | u64 used; | ||
4058 | spin_lock(&root->node_lock); | ||
4059 | used = btrfs_root_used(&root->root_item) - blocksize; | ||
4060 | btrfs_set_root_used(&root->root_item, used); | ||
4061 | spin_unlock(&root->node_lock); | ||
4062 | |||
4063 | return btrfs_free_extent(trans, root, bytenr, blocksize, | ||
4064 | parent, root_objectid, level, 0); | ||
4065 | } | ||
4066 | |||
4052 | static u64 stripe_align(struct btrfs_root *root, u64 val) | 4067 | static u64 stripe_align(struct btrfs_root *root, u64 val) |
4053 | { | 4068 | { |
4054 | u64 mask = ((u64)root->stripesize - 1); | 4069 | u64 mask = ((u64)root->stripesize - 1); |
@@ -4578,7 +4593,6 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans, | |||
4578 | { | 4593 | { |
4579 | int ret; | 4594 | int ret; |
4580 | u64 search_start = 0; | 4595 | u64 search_start = 0; |
4581 | struct btrfs_fs_info *info = root->fs_info; | ||
4582 | 4596 | ||
4583 | data = btrfs_get_alloc_profile(root, data); | 4597 | data = btrfs_get_alloc_profile(root, data); |
4584 | again: | 4598 | again: |
@@ -4586,17 +4600,9 @@ again: | |||
4586 | * the only place that sets empty_size is btrfs_realloc_node, which | 4600 | * the only place that sets empty_size is btrfs_realloc_node, which |
4587 | * is not called recursively on allocations | 4601 | * is not called recursively on allocations |
4588 | */ | 4602 | */ |
4589 | if (empty_size || root->ref_cows) { | 4603 | if (empty_size || root->ref_cows) |
4590 | if (!(data & BTRFS_BLOCK_GROUP_METADATA)) { | ||
4591 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | ||
4592 | 2 * 1024 * 1024, | ||
4593 | BTRFS_BLOCK_GROUP_METADATA | | ||
4594 | (info->metadata_alloc_profile & | ||
4595 | info->avail_metadata_alloc_bits), 0); | ||
4596 | } | ||
4597 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | 4604 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, |
4598 | num_bytes + 2 * 1024 * 1024, data, 0); | 4605 | num_bytes + 2 * 1024 * 1024, data, 0); |
4599 | } | ||
4600 | 4606 | ||
4601 | WARN_ON(num_bytes < root->sectorsize); | 4607 | WARN_ON(num_bytes < root->sectorsize); |
4602 | ret = find_free_extent(trans, root, num_bytes, empty_size, | 4608 | ret = find_free_extent(trans, root, num_bytes, empty_size, |
@@ -4897,6 +4903,14 @@ static int alloc_tree_block(struct btrfs_trans_handle *trans, | |||
4897 | extent_op); | 4903 | extent_op); |
4898 | BUG_ON(ret); | 4904 | BUG_ON(ret); |
4899 | } | 4905 | } |
4906 | |||
4907 | if (root_objectid == root->root_key.objectid) { | ||
4908 | u64 used; | ||
4909 | spin_lock(&root->node_lock); | ||
4910 | used = btrfs_root_used(&root->root_item) + num_bytes; | ||
4911 | btrfs_set_root_used(&root->root_item, used); | ||
4912 | spin_unlock(&root->node_lock); | ||
4913 | } | ||
4900 | return ret; | 4914 | return ret; |
4901 | } | 4915 | } |
4902 | 4916 | ||
@@ -4919,8 +4933,16 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, | |||
4919 | btrfs_set_buffer_uptodate(buf); | 4933 | btrfs_set_buffer_uptodate(buf); |
4920 | 4934 | ||
4921 | if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) { | 4935 | if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) { |
4922 | set_extent_dirty(&root->dirty_log_pages, buf->start, | 4936 | /* |
4923 | buf->start + buf->len - 1, GFP_NOFS); | 4937 | * we allow two log transactions at a time, use different |
4938 | * EXENT bit to differentiate dirty pages. | ||
4939 | */ | ||
4940 | if (root->log_transid % 2 == 0) | ||
4941 | set_extent_dirty(&root->dirty_log_pages, buf->start, | ||
4942 | buf->start + buf->len - 1, GFP_NOFS); | ||
4943 | else | ||
4944 | set_extent_new(&root->dirty_log_pages, buf->start, | ||
4945 | buf->start + buf->len - 1, GFP_NOFS); | ||
4924 | } else { | 4946 | } else { |
4925 | set_extent_dirty(&trans->transaction->dirty_pages, buf->start, | 4947 | set_extent_dirty(&trans->transaction->dirty_pages, buf->start, |
4926 | buf->start + buf->len - 1, GFP_NOFS); | 4948 | buf->start + buf->len - 1, GFP_NOFS); |