diff options
author | Chris Mason <clm@fb.com> | 2016-05-17 17:43:19 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2016-05-17 17:43:19 -0400 |
commit | c315ef8d9db7f1a0ebd023a395ebdfde1c68057e (patch) | |
tree | 501e1fc558de9e56b78e457aa928fa255e660486 /fs/btrfs/extent-tree.c | |
parent | a88336d13c66fc171f336c6332fcb67339894e08 (diff) | |
parent | 5f9a8a51d8b95505d8de8b7191ae2ed8c504d4af (diff) |
Merge branch 'for-chris-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/fdmanana/linux into for-linus-4.7
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 122 |
1 files changed, 116 insertions, 6 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 290e05671ee4..9424864fd01a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3824,6 +3824,59 @@ int btrfs_extent_readonly(struct btrfs_root *root, u64 bytenr) | |||
3824 | return readonly; | 3824 | return readonly; |
3825 | } | 3825 | } |
3826 | 3826 | ||
3827 | bool btrfs_inc_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr) | ||
3828 | { | ||
3829 | struct btrfs_block_group_cache *bg; | ||
3830 | bool ret = true; | ||
3831 | |||
3832 | bg = btrfs_lookup_block_group(fs_info, bytenr); | ||
3833 | if (!bg) | ||
3834 | return false; | ||
3835 | |||
3836 | spin_lock(&bg->lock); | ||
3837 | if (bg->ro) | ||
3838 | ret = false; | ||
3839 | else | ||
3840 | atomic_inc(&bg->nocow_writers); | ||
3841 | spin_unlock(&bg->lock); | ||
3842 | |||
3843 | /* no put on block group, done by btrfs_dec_nocow_writers */ | ||
3844 | if (!ret) | ||
3845 | btrfs_put_block_group(bg); | ||
3846 | |||
3847 | return ret; | ||
3848 | |||
3849 | } | ||
3850 | |||
3851 | void btrfs_dec_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr) | ||
3852 | { | ||
3853 | struct btrfs_block_group_cache *bg; | ||
3854 | |||
3855 | bg = btrfs_lookup_block_group(fs_info, bytenr); | ||
3856 | ASSERT(bg); | ||
3857 | if (atomic_dec_and_test(&bg->nocow_writers)) | ||
3858 | wake_up_atomic_t(&bg->nocow_writers); | ||
3859 | /* | ||
3860 | * Once for our lookup and once for the lookup done by a previous call | ||
3861 | * to btrfs_inc_nocow_writers() | ||
3862 | */ | ||
3863 | btrfs_put_block_group(bg); | ||
3864 | btrfs_put_block_group(bg); | ||
3865 | } | ||
3866 | |||
3867 | static int btrfs_wait_nocow_writers_atomic_t(atomic_t *a) | ||
3868 | { | ||
3869 | schedule(); | ||
3870 | return 0; | ||
3871 | } | ||
3872 | |||
3873 | void btrfs_wait_nocow_writers(struct btrfs_block_group_cache *bg) | ||
3874 | { | ||
3875 | wait_on_atomic_t(&bg->nocow_writers, | ||
3876 | btrfs_wait_nocow_writers_atomic_t, | ||
3877 | TASK_UNINTERRUPTIBLE); | ||
3878 | } | ||
3879 | |||
3827 | static const char *alloc_name(u64 flags) | 3880 | static const char *alloc_name(u64 flags) |
3828 | { | 3881 | { |
3829 | switch (flags) { | 3882 | switch (flags) { |
@@ -4141,7 +4194,7 @@ commit_trans: | |||
4141 | 4194 | ||
4142 | if (need_commit > 0) { | 4195 | if (need_commit > 0) { |
4143 | btrfs_start_delalloc_roots(fs_info, 0, -1); | 4196 | btrfs_start_delalloc_roots(fs_info, 0, -1); |
4144 | btrfs_wait_ordered_roots(fs_info, -1); | 4197 | btrfs_wait_ordered_roots(fs_info, -1, 0, (u64)-1); |
4145 | } | 4198 | } |
4146 | 4199 | ||
4147 | trans = btrfs_join_transaction(root); | 4200 | trans = btrfs_join_transaction(root); |
@@ -4583,7 +4636,8 @@ static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root, | |||
4583 | */ | 4636 | */ |
4584 | btrfs_start_delalloc_roots(root->fs_info, 0, nr_items); | 4637 | btrfs_start_delalloc_roots(root->fs_info, 0, nr_items); |
4585 | if (!current->journal_info) | 4638 | if (!current->journal_info) |
4586 | btrfs_wait_ordered_roots(root->fs_info, nr_items); | 4639 | btrfs_wait_ordered_roots(root->fs_info, nr_items, |
4640 | 0, (u64)-1); | ||
4587 | } | 4641 | } |
4588 | } | 4642 | } |
4589 | 4643 | ||
@@ -4632,7 +4686,8 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, | |||
4632 | if (trans) | 4686 | if (trans) |
4633 | return; | 4687 | return; |
4634 | if (wait_ordered) | 4688 | if (wait_ordered) |
4635 | btrfs_wait_ordered_roots(root->fs_info, items); | 4689 | btrfs_wait_ordered_roots(root->fs_info, items, |
4690 | 0, (u64)-1); | ||
4636 | return; | 4691 | return; |
4637 | } | 4692 | } |
4638 | 4693 | ||
@@ -4671,7 +4726,8 @@ skip_async: | |||
4671 | 4726 | ||
4672 | loops++; | 4727 | loops++; |
4673 | if (wait_ordered && !trans) { | 4728 | if (wait_ordered && !trans) { |
4674 | btrfs_wait_ordered_roots(root->fs_info, items); | 4729 | btrfs_wait_ordered_roots(root->fs_info, items, |
4730 | 0, (u64)-1); | ||
4675 | } else { | 4731 | } else { |
4676 | time_left = schedule_timeout_killable(1); | 4732 | time_left = schedule_timeout_killable(1); |
4677 | if (time_left) | 4733 | if (time_left) |
@@ -6172,6 +6228,57 @@ int btrfs_exclude_logged_extents(struct btrfs_root *log, | |||
6172 | return 0; | 6228 | return 0; |
6173 | } | 6229 | } |
6174 | 6230 | ||
6231 | static void | ||
6232 | btrfs_inc_block_group_reservations(struct btrfs_block_group_cache *bg) | ||
6233 | { | ||
6234 | atomic_inc(&bg->reservations); | ||
6235 | } | ||
6236 | |||
6237 | void btrfs_dec_block_group_reservations(struct btrfs_fs_info *fs_info, | ||
6238 | const u64 start) | ||
6239 | { | ||
6240 | struct btrfs_block_group_cache *bg; | ||
6241 | |||
6242 | bg = btrfs_lookup_block_group(fs_info, start); | ||
6243 | ASSERT(bg); | ||
6244 | if (atomic_dec_and_test(&bg->reservations)) | ||
6245 | wake_up_atomic_t(&bg->reservations); | ||
6246 | btrfs_put_block_group(bg); | ||
6247 | } | ||
6248 | |||
6249 | static int btrfs_wait_bg_reservations_atomic_t(atomic_t *a) | ||
6250 | { | ||
6251 | schedule(); | ||
6252 | return 0; | ||
6253 | } | ||
6254 | |||
6255 | void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg) | ||
6256 | { | ||
6257 | struct btrfs_space_info *space_info = bg->space_info; | ||
6258 | |||
6259 | ASSERT(bg->ro); | ||
6260 | |||
6261 | if (!(bg->flags & BTRFS_BLOCK_GROUP_DATA)) | ||
6262 | return; | ||
6263 | |||
6264 | /* | ||
6265 | * Our block group is read only but before we set it to read only, | ||
6266 | * some task might have had allocated an extent from it already, but it | ||
6267 | * has not yet created a respective ordered extent (and added it to a | ||
6268 | * root's list of ordered extents). | ||
6269 | * Therefore wait for any task currently allocating extents, since the | ||
6270 | * block group's reservations counter is incremented while a read lock | ||
6271 | * on the groups' semaphore is held and decremented after releasing | ||
6272 | * the read access on that semaphore and creating the ordered extent. | ||
6273 | */ | ||
6274 | down_write(&space_info->groups_sem); | ||
6275 | up_write(&space_info->groups_sem); | ||
6276 | |||
6277 | wait_on_atomic_t(&bg->reservations, | ||
6278 | btrfs_wait_bg_reservations_atomic_t, | ||
6279 | TASK_UNINTERRUPTIBLE); | ||
6280 | } | ||
6281 | |||
6175 | /** | 6282 | /** |
6176 | * btrfs_update_reserved_bytes - update the block_group and space info counters | 6283 | * btrfs_update_reserved_bytes - update the block_group and space info counters |
6177 | * @cache: The cache we are manipulating | 6284 | * @cache: The cache we are manipulating |
@@ -7430,6 +7537,7 @@ checks: | |||
7430 | btrfs_add_free_space(block_group, offset, num_bytes); | 7537 | btrfs_add_free_space(block_group, offset, num_bytes); |
7431 | goto loop; | 7538 | goto loop; |
7432 | } | 7539 | } |
7540 | btrfs_inc_block_group_reservations(block_group); | ||
7433 | 7541 | ||
7434 | /* we are all good, lets return */ | 7542 | /* we are all good, lets return */ |
7435 | ins->objectid = search_start; | 7543 | ins->objectid = search_start; |
@@ -7611,8 +7719,10 @@ again: | |||
7611 | WARN_ON(num_bytes < root->sectorsize); | 7719 | WARN_ON(num_bytes < root->sectorsize); |
7612 | ret = find_free_extent(root, num_bytes, empty_size, hint_byte, ins, | 7720 | ret = find_free_extent(root, num_bytes, empty_size, hint_byte, ins, |
7613 | flags, delalloc); | 7721 | flags, delalloc); |
7614 | 7722 | if (!ret && !is_data) { | |
7615 | if (ret == -ENOSPC) { | 7723 | btrfs_dec_block_group_reservations(root->fs_info, |
7724 | ins->objectid); | ||
7725 | } else if (ret == -ENOSPC) { | ||
7616 | if (!final_tried && ins->offset) { | 7726 | if (!final_tried && ins->offset) { |
7617 | num_bytes = min(num_bytes >> 1, ins->offset); | 7727 | num_bytes = min(num_bytes >> 1, ins->offset); |
7618 | num_bytes = round_down(num_bytes, root->sectorsize); | 7728 | num_bytes = round_down(num_bytes, root->sectorsize); |