diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
| -rw-r--r-- | fs/btrfs/extent-tree.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 588ff984987..7b3089b5c2d 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -3342,15 +3342,16 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, | |||
| 3342 | u64 max_reclaim; | 3342 | u64 max_reclaim; |
| 3343 | u64 reclaimed = 0; | 3343 | u64 reclaimed = 0; |
| 3344 | long time_left; | 3344 | long time_left; |
| 3345 | int pause = 1; | ||
| 3346 | int nr_pages = (2 * 1024 * 1024) >> PAGE_CACHE_SHIFT; | 3345 | int nr_pages = (2 * 1024 * 1024) >> PAGE_CACHE_SHIFT; |
| 3347 | int loops = 0; | 3346 | int loops = 0; |
| 3347 | unsigned long progress; | ||
| 3348 | 3348 | ||
| 3349 | block_rsv = &root->fs_info->delalloc_block_rsv; | 3349 | block_rsv = &root->fs_info->delalloc_block_rsv; |
| 3350 | space_info = block_rsv->space_info; | 3350 | space_info = block_rsv->space_info; |
| 3351 | 3351 | ||
| 3352 | smp_mb(); | 3352 | smp_mb(); |
| 3353 | reserved = space_info->bytes_reserved; | 3353 | reserved = space_info->bytes_reserved; |
| 3354 | progress = space_info->reservation_progress; | ||
| 3354 | 3355 | ||
| 3355 | if (reserved == 0) | 3356 | if (reserved == 0) |
| 3356 | return 0; | 3357 | return 0; |
| @@ -3365,31 +3366,36 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, | |||
| 3365 | writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages); | 3366 | writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages); |
| 3366 | 3367 | ||
| 3367 | spin_lock(&space_info->lock); | 3368 | spin_lock(&space_info->lock); |
| 3368 | if (reserved > space_info->bytes_reserved) { | 3369 | if (reserved > space_info->bytes_reserved) |
| 3369 | loops = 0; | ||
| 3370 | reclaimed += reserved - space_info->bytes_reserved; | 3370 | reclaimed += reserved - space_info->bytes_reserved; |
| 3371 | } else { | ||
| 3372 | loops++; | ||
| 3373 | } | ||
| 3374 | reserved = space_info->bytes_reserved; | 3371 | reserved = space_info->bytes_reserved; |
| 3375 | spin_unlock(&space_info->lock); | 3372 | spin_unlock(&space_info->lock); |
| 3376 | 3373 | ||
| 3374 | loops++; | ||
| 3375 | |||
| 3377 | if (reserved == 0 || reclaimed >= max_reclaim) | 3376 | if (reserved == 0 || reclaimed >= max_reclaim) |
| 3378 | break; | 3377 | break; |
| 3379 | 3378 | ||
| 3380 | if (trans && trans->transaction->blocked) | 3379 | if (trans && trans->transaction->blocked) |
| 3381 | return -EAGAIN; | 3380 | return -EAGAIN; |
| 3382 | 3381 | ||
| 3383 | __set_current_state(TASK_INTERRUPTIBLE); | 3382 | time_left = schedule_timeout_interruptible(1); |
| 3384 | time_left = schedule_timeout(pause); | ||
| 3385 | 3383 | ||
| 3386 | /* We were interrupted, exit */ | 3384 | /* We were interrupted, exit */ |
| 3387 | if (time_left) | 3385 | if (time_left) |
| 3388 | break; | 3386 | break; |
| 3389 | 3387 | ||
| 3390 | pause <<= 1; | 3388 | /* we've kicked the IO a few times, if anything has been freed, |
| 3391 | if (pause > HZ / 10) | 3389 | * exit. There is no sense in looping here for a long time |
| 3392 | pause = HZ / 10; | 3390 | * when we really need to commit the transaction, or there are |
| 3391 | * just too many writers without enough free space | ||
| 3392 | */ | ||
| 3393 | |||
| 3394 | if (loops > 3) { | ||
| 3395 | smp_mb(); | ||
| 3396 | if (progress != space_info->reservation_progress) | ||
| 3397 | break; | ||
| 3398 | } | ||
| 3393 | 3399 | ||
| 3394 | } | 3400 | } |
| 3395 | return reclaimed >= to_reclaim; | 3401 | return reclaimed >= to_reclaim; |
| @@ -3612,6 +3618,7 @@ void block_rsv_release_bytes(struct btrfs_block_rsv *block_rsv, | |||
| 3612 | if (num_bytes) { | 3618 | if (num_bytes) { |
| 3613 | spin_lock(&space_info->lock); | 3619 | spin_lock(&space_info->lock); |
| 3614 | space_info->bytes_reserved -= num_bytes; | 3620 | space_info->bytes_reserved -= num_bytes; |
| 3621 | space_info->reservation_progress++; | ||
| 3615 | spin_unlock(&space_info->lock); | 3622 | spin_unlock(&space_info->lock); |
| 3616 | } | 3623 | } |
| 3617 | } | 3624 | } |
| @@ -3844,6 +3851,7 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info) | |||
| 3844 | if (block_rsv->reserved >= block_rsv->size) { | 3851 | if (block_rsv->reserved >= block_rsv->size) { |
| 3845 | num_bytes = block_rsv->reserved - block_rsv->size; | 3852 | num_bytes = block_rsv->reserved - block_rsv->size; |
| 3846 | sinfo->bytes_reserved -= num_bytes; | 3853 | sinfo->bytes_reserved -= num_bytes; |
| 3854 | sinfo->reservation_progress++; | ||
| 3847 | block_rsv->reserved = block_rsv->size; | 3855 | block_rsv->reserved = block_rsv->size; |
| 3848 | block_rsv->full = 1; | 3856 | block_rsv->full = 1; |
| 3849 | } | 3857 | } |
| @@ -4005,7 +4013,6 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
| 4005 | to_reserve = 0; | 4013 | to_reserve = 0; |
| 4006 | } | 4014 | } |
| 4007 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | 4015 | spin_unlock(&BTRFS_I(inode)->accounting_lock); |
| 4008 | |||
| 4009 | to_reserve += calc_csum_metadata_size(inode, num_bytes); | 4016 | to_reserve += calc_csum_metadata_size(inode, num_bytes); |
| 4010 | ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); | 4017 | ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); |
| 4011 | if (ret) | 4018 | if (ret) |
| @@ -4133,6 +4140,7 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
| 4133 | btrfs_set_block_group_used(&cache->item, old_val); | 4140 | btrfs_set_block_group_used(&cache->item, old_val); |
| 4134 | cache->reserved -= num_bytes; | 4141 | cache->reserved -= num_bytes; |
| 4135 | cache->space_info->bytes_reserved -= num_bytes; | 4142 | cache->space_info->bytes_reserved -= num_bytes; |
| 4143 | cache->space_info->reservation_progress++; | ||
| 4136 | cache->space_info->bytes_used += num_bytes; | 4144 | cache->space_info->bytes_used += num_bytes; |
| 4137 | cache->space_info->disk_used += num_bytes * factor; | 4145 | cache->space_info->disk_used += num_bytes * factor; |
| 4138 | spin_unlock(&cache->lock); | 4146 | spin_unlock(&cache->lock); |
| @@ -4184,6 +4192,7 @@ static int pin_down_extent(struct btrfs_root *root, | |||
| 4184 | if (reserved) { | 4192 | if (reserved) { |
| 4185 | cache->reserved -= num_bytes; | 4193 | cache->reserved -= num_bytes; |
| 4186 | cache->space_info->bytes_reserved -= num_bytes; | 4194 | cache->space_info->bytes_reserved -= num_bytes; |
| 4195 | cache->space_info->reservation_progress++; | ||
| 4187 | } | 4196 | } |
| 4188 | spin_unlock(&cache->lock); | 4197 | spin_unlock(&cache->lock); |
| 4189 | spin_unlock(&cache->space_info->lock); | 4198 | spin_unlock(&cache->space_info->lock); |
| @@ -4234,6 +4243,7 @@ static int update_reserved_bytes(struct btrfs_block_group_cache *cache, | |||
| 4234 | space_info->bytes_readonly += num_bytes; | 4243 | space_info->bytes_readonly += num_bytes; |
| 4235 | cache->reserved -= num_bytes; | 4244 | cache->reserved -= num_bytes; |
| 4236 | space_info->bytes_reserved -= num_bytes; | 4245 | space_info->bytes_reserved -= num_bytes; |
| 4246 | space_info->reservation_progress++; | ||
| 4237 | } | 4247 | } |
| 4238 | spin_unlock(&cache->lock); | 4248 | spin_unlock(&cache->lock); |
| 4239 | spin_unlock(&space_info->lock); | 4249 | spin_unlock(&space_info->lock); |
| @@ -4712,6 +4722,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, | |||
| 4712 | if (ret) { | 4722 | if (ret) { |
| 4713 | spin_lock(&cache->space_info->lock); | 4723 | spin_lock(&cache->space_info->lock); |
| 4714 | cache->space_info->bytes_reserved -= buf->len; | 4724 | cache->space_info->bytes_reserved -= buf->len; |
| 4725 | cache->space_info->reservation_progress++; | ||
| 4715 | spin_unlock(&cache->space_info->lock); | 4726 | spin_unlock(&cache->space_info->lock); |
| 4716 | } | 4727 | } |
| 4717 | goto out; | 4728 | goto out; |
