diff options
-rw-r--r-- | fs/btrfs/extent-tree.c | 74 |
1 files changed, 31 insertions, 43 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index db0b23b14f20..05e1386b8bec 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -5106,11 +5106,11 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
5106 | struct btrfs_root *root = orig_root->fs_info->extent_root; | 5106 | struct btrfs_root *root = orig_root->fs_info->extent_root; |
5107 | struct btrfs_free_cluster *last_ptr = NULL; | 5107 | struct btrfs_free_cluster *last_ptr = NULL; |
5108 | struct btrfs_block_group_cache *block_group = NULL; | 5108 | struct btrfs_block_group_cache *block_group = NULL; |
5109 | struct btrfs_block_group_cache *used_block_group; | ||
5109 | int empty_cluster = 2 * 1024 * 1024; | 5110 | int empty_cluster = 2 * 1024 * 1024; |
5110 | int allowed_chunk_alloc = 0; | 5111 | int allowed_chunk_alloc = 0; |
5111 | int done_chunk_alloc = 0; | 5112 | int done_chunk_alloc = 0; |
5112 | struct btrfs_space_info *space_info; | 5113 | struct btrfs_space_info *space_info; |
5113 | int last_ptr_loop = 0; | ||
5114 | int loop = 0; | 5114 | int loop = 0; |
5115 | int index = 0; | 5115 | int index = 0; |
5116 | int alloc_type = (data & BTRFS_BLOCK_GROUP_DATA) ? | 5116 | int alloc_type = (data & BTRFS_BLOCK_GROUP_DATA) ? |
@@ -5172,6 +5172,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
5172 | ideal_cache: | 5172 | ideal_cache: |
5173 | block_group = btrfs_lookup_block_group(root->fs_info, | 5173 | block_group = btrfs_lookup_block_group(root->fs_info, |
5174 | search_start); | 5174 | search_start); |
5175 | used_block_group = block_group; | ||
5175 | /* | 5176 | /* |
5176 | * we don't want to use the block group if it doesn't match our | 5177 | * we don't want to use the block group if it doesn't match our |
5177 | * allocation bits, or if its not cached. | 5178 | * allocation bits, or if its not cached. |
@@ -5209,6 +5210,7 @@ search: | |||
5209 | u64 offset; | 5210 | u64 offset; |
5210 | int cached; | 5211 | int cached; |
5211 | 5212 | ||
5213 | used_block_group = block_group; | ||
5212 | btrfs_get_block_group(block_group); | 5214 | btrfs_get_block_group(block_group); |
5213 | search_start = block_group->key.objectid; | 5215 | search_start = block_group->key.objectid; |
5214 | 5216 | ||
@@ -5294,49 +5296,33 @@ alloc: | |||
5294 | * people trying to start a new cluster | 5296 | * people trying to start a new cluster |
5295 | */ | 5297 | */ |
5296 | spin_lock(&last_ptr->refill_lock); | 5298 | spin_lock(&last_ptr->refill_lock); |
5297 | if (!last_ptr->block_group || | 5299 | used_block_group = last_ptr->block_group; |
5298 | last_ptr->block_group->ro || | 5300 | if (used_block_group != block_group && |
5299 | !block_group_bits(last_ptr->block_group, data)) | 5301 | (!used_block_group || |
5302 | used_block_group->ro || | ||
5303 | !block_group_bits(used_block_group, data))) { | ||
5304 | used_block_group = block_group; | ||
5300 | goto refill_cluster; | 5305 | goto refill_cluster; |
5306 | } | ||
5307 | |||
5308 | if (used_block_group != block_group) | ||
5309 | btrfs_get_block_group(used_block_group); | ||
5301 | 5310 | ||
5302 | offset = btrfs_alloc_from_cluster(block_group, last_ptr, | 5311 | offset = btrfs_alloc_from_cluster(used_block_group, |
5303 | num_bytes, search_start); | 5312 | last_ptr, num_bytes, used_block_group->key.objectid); |
5304 | if (offset) { | 5313 | if (offset) { |
5305 | /* we have a block, we're done */ | 5314 | /* we have a block, we're done */ |
5306 | spin_unlock(&last_ptr->refill_lock); | 5315 | spin_unlock(&last_ptr->refill_lock); |
5307 | goto checks; | 5316 | goto checks; |
5308 | } | 5317 | } |
5309 | 5318 | ||
5310 | spin_lock(&last_ptr->lock); | 5319 | WARN_ON(last_ptr->block_group != used_block_group); |
5311 | /* | 5320 | if (used_block_group != block_group) { |
5312 | * whoops, this cluster doesn't actually point to | 5321 | btrfs_put_block_group(used_block_group); |
5313 | * this block group. Get a ref on the block | 5322 | used_block_group = block_group; |
5314 | * group is does point to and try again | ||
5315 | */ | ||
5316 | if (!last_ptr_loop && last_ptr->block_group && | ||
5317 | last_ptr->block_group != block_group && | ||
5318 | index <= | ||
5319 | get_block_group_index(last_ptr->block_group)) { | ||
5320 | |||
5321 | btrfs_put_block_group(block_group); | ||
5322 | block_group = last_ptr->block_group; | ||
5323 | btrfs_get_block_group(block_group); | ||
5324 | spin_unlock(&last_ptr->lock); | ||
5325 | spin_unlock(&last_ptr->refill_lock); | ||
5326 | |||
5327 | last_ptr_loop = 1; | ||
5328 | search_start = block_group->key.objectid; | ||
5329 | /* | ||
5330 | * we know this block group is properly | ||
5331 | * in the list because | ||
5332 | * btrfs_remove_block_group, drops the | ||
5333 | * cluster before it removes the block | ||
5334 | * group from the list | ||
5335 | */ | ||
5336 | goto have_block_group; | ||
5337 | } | 5323 | } |
5338 | spin_unlock(&last_ptr->lock); | ||
5339 | refill_cluster: | 5324 | refill_cluster: |
5325 | BUG_ON(used_block_group != block_group); | ||
5340 | /* If we are on LOOP_NO_EMPTY_SIZE, we can't | 5326 | /* If we are on LOOP_NO_EMPTY_SIZE, we can't |
5341 | * set up a new clusters, so lets just skip it | 5327 | * set up a new clusters, so lets just skip it |
5342 | * and let the allocator find whatever block | 5328 | * and let the allocator find whatever block |
@@ -5357,8 +5343,6 @@ refill_cluster: | |||
5357 | */ | 5343 | */ |
5358 | btrfs_return_cluster_to_free_space(NULL, last_ptr); | 5344 | btrfs_return_cluster_to_free_space(NULL, last_ptr); |
5359 | 5345 | ||
5360 | last_ptr_loop = 0; | ||
5361 | |||
5362 | /* allocate a cluster in this block group */ | 5346 | /* allocate a cluster in this block group */ |
5363 | ret = btrfs_find_space_cluster(trans, root, | 5347 | ret = btrfs_find_space_cluster(trans, root, |
5364 | block_group, last_ptr, | 5348 | block_group, last_ptr, |
@@ -5425,14 +5409,14 @@ checks: | |||
5425 | search_start = stripe_align(root, offset); | 5409 | search_start = stripe_align(root, offset); |
5426 | /* move on to the next group */ | 5410 | /* move on to the next group */ |
5427 | if (search_start + num_bytes >= search_end) { | 5411 | if (search_start + num_bytes >= search_end) { |
5428 | btrfs_add_free_space(block_group, offset, num_bytes); | 5412 | btrfs_add_free_space(used_block_group, offset, num_bytes); |
5429 | goto loop; | 5413 | goto loop; |
5430 | } | 5414 | } |
5431 | 5415 | ||
5432 | /* move on to the next group */ | 5416 | /* move on to the next group */ |
5433 | if (search_start + num_bytes > | 5417 | if (search_start + num_bytes > |
5434 | block_group->key.objectid + block_group->key.offset) { | 5418 | used_block_group->key.objectid + used_block_group->key.offset) { |
5435 | btrfs_add_free_space(block_group, offset, num_bytes); | 5419 | btrfs_add_free_space(used_block_group, offset, num_bytes); |
5436 | goto loop; | 5420 | goto loop; |
5437 | } | 5421 | } |
5438 | 5422 | ||
@@ -5440,14 +5424,14 @@ checks: | |||
5440 | ins->offset = num_bytes; | 5424 | ins->offset = num_bytes; |
5441 | 5425 | ||
5442 | if (offset < search_start) | 5426 | if (offset < search_start) |
5443 | btrfs_add_free_space(block_group, offset, | 5427 | btrfs_add_free_space(used_block_group, offset, |
5444 | search_start - offset); | 5428 | search_start - offset); |
5445 | BUG_ON(offset > search_start); | 5429 | BUG_ON(offset > search_start); |
5446 | 5430 | ||
5447 | ret = btrfs_update_reserved_bytes(block_group, num_bytes, | 5431 | ret = btrfs_update_reserved_bytes(used_block_group, num_bytes, |
5448 | alloc_type); | 5432 | alloc_type); |
5449 | if (ret == -EAGAIN) { | 5433 | if (ret == -EAGAIN) { |
5450 | btrfs_add_free_space(block_group, offset, num_bytes); | 5434 | btrfs_add_free_space(used_block_group, offset, num_bytes); |
5451 | goto loop; | 5435 | goto loop; |
5452 | } | 5436 | } |
5453 | 5437 | ||
@@ -5456,15 +5440,19 @@ checks: | |||
5456 | ins->offset = num_bytes; | 5440 | ins->offset = num_bytes; |
5457 | 5441 | ||
5458 | if (offset < search_start) | 5442 | if (offset < search_start) |
5459 | btrfs_add_free_space(block_group, offset, | 5443 | btrfs_add_free_space(used_block_group, offset, |
5460 | search_start - offset); | 5444 | search_start - offset); |
5461 | BUG_ON(offset > search_start); | 5445 | BUG_ON(offset > search_start); |
5446 | if (used_block_group != block_group) | ||
5447 | btrfs_put_block_group(used_block_group); | ||
5462 | btrfs_put_block_group(block_group); | 5448 | btrfs_put_block_group(block_group); |
5463 | break; | 5449 | break; |
5464 | loop: | 5450 | loop: |
5465 | failed_cluster_refill = false; | 5451 | failed_cluster_refill = false; |
5466 | failed_alloc = false; | 5452 | failed_alloc = false; |
5467 | BUG_ON(index != get_block_group_index(block_group)); | 5453 | BUG_ON(index != get_block_group_index(block_group)); |
5454 | if (used_block_group != block_group) | ||
5455 | btrfs_put_block_group(used_block_group); | ||
5468 | btrfs_put_block_group(block_group); | 5456 | btrfs_put_block_group(block_group); |
5469 | } | 5457 | } |
5470 | up_read(&space_info->groups_sem); | 5458 | up_read(&space_info->groups_sem); |