diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 559f72489b3b..c6a4f459ad76 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/sort.h> | 22 | #include <linux/sort.h> |
23 | #include <linux/rcupdate.h> | 23 | #include <linux/rcupdate.h> |
24 | #include <linux/kthread.h> | 24 | #include <linux/kthread.h> |
25 | #include <linux/slab.h> | ||
25 | #include "compat.h" | 26 | #include "compat.h" |
26 | #include "hash.h" | 27 | #include "hash.h" |
27 | #include "ctree.h" | 28 | #include "ctree.h" |
@@ -1588,7 +1589,7 @@ static void btrfs_issue_discard(struct block_device *bdev, | |||
1588 | u64 start, u64 len) | 1589 | u64 start, u64 len) |
1589 | { | 1590 | { |
1590 | blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL, | 1591 | blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL, |
1591 | DISCARD_FL_BARRIER); | 1592 | BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER); |
1592 | } | 1593 | } |
1593 | 1594 | ||
1594 | static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, | 1595 | static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, |
@@ -2676,6 +2677,8 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
2676 | 2677 | ||
2677 | INIT_LIST_HEAD(&found->block_groups); | 2678 | INIT_LIST_HEAD(&found->block_groups); |
2678 | init_rwsem(&found->groups_sem); | 2679 | init_rwsem(&found->groups_sem); |
2680 | init_waitqueue_head(&found->flush_wait); | ||
2681 | init_waitqueue_head(&found->allocate_wait); | ||
2679 | spin_lock_init(&found->lock); | 2682 | spin_lock_init(&found->lock); |
2680 | found->flags = flags; | 2683 | found->flags = flags; |
2681 | found->total_bytes = total_bytes; | 2684 | found->total_bytes = total_bytes; |
@@ -2846,7 +2849,7 @@ int btrfs_unreserve_metadata_for_delalloc(struct btrfs_root *root, | |||
2846 | } | 2849 | } |
2847 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | 2850 | spin_unlock(&BTRFS_I(inode)->accounting_lock); |
2848 | 2851 | ||
2849 | BTRFS_I(inode)->reserved_extents--; | 2852 | BTRFS_I(inode)->reserved_extents -= num_items; |
2850 | BUG_ON(BTRFS_I(inode)->reserved_extents < 0); | 2853 | BUG_ON(BTRFS_I(inode)->reserved_extents < 0); |
2851 | 2854 | ||
2852 | if (meta_sinfo->bytes_delalloc < num_bytes) { | 2855 | if (meta_sinfo->bytes_delalloc < num_bytes) { |
@@ -2944,12 +2947,10 @@ static void flush_delalloc(struct btrfs_root *root, | |||
2944 | 2947 | ||
2945 | spin_lock(&info->lock); | 2948 | spin_lock(&info->lock); |
2946 | 2949 | ||
2947 | if (!info->flushing) { | 2950 | if (!info->flushing) |
2948 | info->flushing = 1; | 2951 | info->flushing = 1; |
2949 | init_waitqueue_head(&info->flush_wait); | 2952 | else |
2950 | } else { | ||
2951 | wait = true; | 2953 | wait = true; |
2952 | } | ||
2953 | 2954 | ||
2954 | spin_unlock(&info->lock); | 2955 | spin_unlock(&info->lock); |
2955 | 2956 | ||
@@ -3011,7 +3012,6 @@ static int maybe_allocate_chunk(struct btrfs_root *root, | |||
3011 | if (!info->allocating_chunk) { | 3012 | if (!info->allocating_chunk) { |
3012 | info->force_alloc = 1; | 3013 | info->force_alloc = 1; |
3013 | info->allocating_chunk = 1; | 3014 | info->allocating_chunk = 1; |
3014 | init_waitqueue_head(&info->allocate_wait); | ||
3015 | } else { | 3015 | } else { |
3016 | wait = true; | 3016 | wait = true; |
3017 | } | 3017 | } |
@@ -3111,7 +3111,7 @@ again: | |||
3111 | return -ENOSPC; | 3111 | return -ENOSPC; |
3112 | } | 3112 | } |
3113 | 3113 | ||
3114 | BTRFS_I(inode)->reserved_extents++; | 3114 | BTRFS_I(inode)->reserved_extents += num_items; |
3115 | check_force_delalloc(meta_sinfo); | 3115 | check_force_delalloc(meta_sinfo); |
3116 | spin_unlock(&meta_sinfo->lock); | 3116 | spin_unlock(&meta_sinfo->lock); |
3117 | 3117 | ||
@@ -3235,7 +3235,8 @@ int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode, | |||
3235 | u64 bytes) | 3235 | u64 bytes) |
3236 | { | 3236 | { |
3237 | struct btrfs_space_info *data_sinfo; | 3237 | struct btrfs_space_info *data_sinfo; |
3238 | int ret = 0, committed = 0; | 3238 | u64 used; |
3239 | int ret = 0, committed = 0, flushed = 0; | ||
3239 | 3240 | ||
3240 | /* make sure bytes are sectorsize aligned */ | 3241 | /* make sure bytes are sectorsize aligned */ |
3241 | bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1); | 3242 | bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1); |
@@ -3247,12 +3248,21 @@ int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode, | |||
3247 | again: | 3248 | again: |
3248 | /* make sure we have enough space to handle the data first */ | 3249 | /* make sure we have enough space to handle the data first */ |
3249 | spin_lock(&data_sinfo->lock); | 3250 | spin_lock(&data_sinfo->lock); |
3250 | if (data_sinfo->total_bytes - data_sinfo->bytes_used - | 3251 | used = data_sinfo->bytes_used + data_sinfo->bytes_delalloc + |
3251 | data_sinfo->bytes_delalloc - data_sinfo->bytes_reserved - | 3252 | data_sinfo->bytes_reserved + data_sinfo->bytes_pinned + |
3252 | data_sinfo->bytes_pinned - data_sinfo->bytes_readonly - | 3253 | data_sinfo->bytes_readonly + data_sinfo->bytes_may_use + |
3253 | data_sinfo->bytes_may_use - data_sinfo->bytes_super < bytes) { | 3254 | data_sinfo->bytes_super; |
3255 | |||
3256 | if (used + bytes > data_sinfo->total_bytes) { | ||
3254 | struct btrfs_trans_handle *trans; | 3257 | struct btrfs_trans_handle *trans; |
3255 | 3258 | ||
3259 | if (!flushed) { | ||
3260 | spin_unlock(&data_sinfo->lock); | ||
3261 | flush_delalloc(root, data_sinfo); | ||
3262 | flushed = 1; | ||
3263 | goto again; | ||
3264 | } | ||
3265 | |||
3256 | /* | 3266 | /* |
3257 | * if we don't have enough free bytes in this space then we need | 3267 | * if we don't have enough free bytes in this space then we need |
3258 | * to alloc a new chunk. | 3268 | * to alloc a new chunk. |
@@ -4170,6 +4180,10 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
4170 | ins->offset = 0; | 4180 | ins->offset = 0; |
4171 | 4181 | ||
4172 | space_info = __find_space_info(root->fs_info, data); | 4182 | space_info = __find_space_info(root->fs_info, data); |
4183 | if (!space_info) { | ||
4184 | printk(KERN_ERR "No space info for %d\n", data); | ||
4185 | return -ENOSPC; | ||
4186 | } | ||
4173 | 4187 | ||
4174 | if (orig_root->ref_cows || empty_size) | 4188 | if (orig_root->ref_cows || empty_size) |
4175 | allowed_chunk_alloc = 1; | 4189 | allowed_chunk_alloc = 1; |
@@ -5205,6 +5219,8 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, | |||
5205 | next = btrfs_find_tree_block(root, bytenr, blocksize); | 5219 | next = btrfs_find_tree_block(root, bytenr, blocksize); |
5206 | if (!next) { | 5220 | if (!next) { |
5207 | next = btrfs_find_create_tree_block(root, bytenr, blocksize); | 5221 | next = btrfs_find_create_tree_block(root, bytenr, blocksize); |
5222 | if (!next) | ||
5223 | return -ENOMEM; | ||
5208 | reada = 1; | 5224 | reada = 1; |
5209 | } | 5225 | } |
5210 | btrfs_tree_lock(next); | 5226 | btrfs_tree_lock(next); |
@@ -5417,7 +5433,8 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans, | |||
5417 | if (ret > 0) { | 5433 | if (ret > 0) { |
5418 | path->slots[level]++; | 5434 | path->slots[level]++; |
5419 | continue; | 5435 | continue; |
5420 | } | 5436 | } else if (ret < 0) |
5437 | return ret; | ||
5421 | level = wc->level; | 5438 | level = wc->level; |
5422 | } | 5439 | } |
5423 | return 0; | 5440 | return 0; |
@@ -6561,6 +6578,7 @@ static noinline int invalidate_extent_cache(struct btrfs_root *root, | |||
6561 | struct btrfs_key key; | 6578 | struct btrfs_key key; |
6562 | struct inode *inode = NULL; | 6579 | struct inode *inode = NULL; |
6563 | struct btrfs_file_extent_item *fi; | 6580 | struct btrfs_file_extent_item *fi; |
6581 | struct extent_state *cached_state = NULL; | ||
6564 | u64 num_bytes; | 6582 | u64 num_bytes; |
6565 | u64 skip_objectid = 0; | 6583 | u64 skip_objectid = 0; |
6566 | u32 nritems; | 6584 | u32 nritems; |
@@ -6589,12 +6607,14 @@ static noinline int invalidate_extent_cache(struct btrfs_root *root, | |||
6589 | } | 6607 | } |
6590 | num_bytes = btrfs_file_extent_num_bytes(leaf, fi); | 6608 | num_bytes = btrfs_file_extent_num_bytes(leaf, fi); |
6591 | 6609 | ||
6592 | lock_extent(&BTRFS_I(inode)->io_tree, key.offset, | 6610 | lock_extent_bits(&BTRFS_I(inode)->io_tree, key.offset, |
6593 | key.offset + num_bytes - 1, GFP_NOFS); | 6611 | key.offset + num_bytes - 1, 0, &cached_state, |
6612 | GFP_NOFS); | ||
6594 | btrfs_drop_extent_cache(inode, key.offset, | 6613 | btrfs_drop_extent_cache(inode, key.offset, |
6595 | key.offset + num_bytes - 1, 1); | 6614 | key.offset + num_bytes - 1, 1); |
6596 | unlock_extent(&BTRFS_I(inode)->io_tree, key.offset, | 6615 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, key.offset, |
6597 | key.offset + num_bytes - 1, GFP_NOFS); | 6616 | key.offset + num_bytes - 1, &cached_state, |
6617 | GFP_NOFS); | ||
6598 | cond_resched(); | 6618 | cond_resched(); |
6599 | } | 6619 | } |
6600 | iput(inode); | 6620 | iput(inode); |
@@ -7366,7 +7386,6 @@ static int find_first_block_group(struct btrfs_root *root, | |||
7366 | } | 7386 | } |
7367 | path->slots[0]++; | 7387 | path->slots[0]++; |
7368 | } | 7388 | } |
7369 | ret = -ENOENT; | ||
7370 | out: | 7389 | out: |
7371 | return ret; | 7390 | return ret; |
7372 | } | 7391 | } |