diff options
| -rw-r--r-- | fs/btrfs/extent-tree.c | 100 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 24 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 2 |
3 files changed, 66 insertions, 60 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index f0d5718d2587..2ad813674d77 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -5107,11 +5107,11 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
| 5107 | struct btrfs_root *root = orig_root->fs_info->extent_root; | 5107 | struct btrfs_root *root = orig_root->fs_info->extent_root; |
| 5108 | struct btrfs_free_cluster *last_ptr = NULL; | 5108 | struct btrfs_free_cluster *last_ptr = NULL; |
| 5109 | struct btrfs_block_group_cache *block_group = NULL; | 5109 | struct btrfs_block_group_cache *block_group = NULL; |
| 5110 | struct btrfs_block_group_cache *used_block_group; | ||
| 5110 | int empty_cluster = 2 * 1024 * 1024; | 5111 | int empty_cluster = 2 * 1024 * 1024; |
| 5111 | int allowed_chunk_alloc = 0; | 5112 | int allowed_chunk_alloc = 0; |
| 5112 | int done_chunk_alloc = 0; | 5113 | int done_chunk_alloc = 0; |
| 5113 | struct btrfs_space_info *space_info; | 5114 | struct btrfs_space_info *space_info; |
| 5114 | int last_ptr_loop = 0; | ||
| 5115 | int loop = 0; | 5115 | int loop = 0; |
| 5116 | int index = 0; | 5116 | int index = 0; |
| 5117 | int alloc_type = (data & BTRFS_BLOCK_GROUP_DATA) ? | 5117 | int alloc_type = (data & BTRFS_BLOCK_GROUP_DATA) ? |
| @@ -5173,6 +5173,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
| 5173 | ideal_cache: | 5173 | ideal_cache: |
| 5174 | block_group = btrfs_lookup_block_group(root->fs_info, | 5174 | block_group = btrfs_lookup_block_group(root->fs_info, |
| 5175 | search_start); | 5175 | search_start); |
| 5176 | used_block_group = block_group; | ||
| 5176 | /* | 5177 | /* |
| 5177 | * we don't want to use the block group if it doesn't match our | 5178 | * we don't want to use the block group if it doesn't match our |
| 5178 | * allocation bits, or if its not cached. | 5179 | * allocation bits, or if its not cached. |
| @@ -5210,6 +5211,7 @@ search: | |||
| 5210 | u64 offset; | 5211 | u64 offset; |
| 5211 | int cached; | 5212 | int cached; |
| 5212 | 5213 | ||
| 5214 | used_block_group = block_group; | ||
| 5213 | btrfs_get_block_group(block_group); | 5215 | btrfs_get_block_group(block_group); |
| 5214 | search_start = block_group->key.objectid; | 5216 | search_start = block_group->key.objectid; |
| 5215 | 5217 | ||
| @@ -5286,71 +5288,62 @@ alloc: | |||
| 5286 | spin_unlock(&block_group->free_space_ctl->tree_lock); | 5288 | spin_unlock(&block_group->free_space_ctl->tree_lock); |
| 5287 | 5289 | ||
| 5288 | /* | 5290 | /* |
| 5289 | * Ok we want to try and use the cluster allocator, so lets look | 5291 | * Ok we want to try and use the cluster allocator, so |
| 5290 | * there, unless we are on LOOP_NO_EMPTY_SIZE, since we will | 5292 | * lets look there |
| 5291 | * have tried the cluster allocator plenty of times at this | ||
| 5292 | * point and not have found anything, so we are likely way too | ||
| 5293 | * fragmented for the clustering stuff to find anything, so lets | ||
| 5294 | * just skip it and let the allocator find whatever block it can | ||
| 5295 | * find | ||
| 5296 | */ | 5293 | */ |
| 5297 | if (last_ptr && loop < LOOP_NO_EMPTY_SIZE) { | 5294 | if (last_ptr) { |
| 5298 | /* | 5295 | /* |
| 5299 | * the refill lock keeps out other | 5296 | * the refill lock keeps out other |
| 5300 | * people trying to start a new cluster | 5297 | * people trying to start a new cluster |
| 5301 | */ | 5298 | */ |
| 5302 | spin_lock(&last_ptr->refill_lock); | 5299 | spin_lock(&last_ptr->refill_lock); |
| 5303 | if (!last_ptr->block_group || | 5300 | used_block_group = last_ptr->block_group; |
| 5304 | last_ptr->block_group->ro || | 5301 | if (used_block_group != block_group && |
| 5305 | !block_group_bits(last_ptr->block_group, data)) | 5302 | (!used_block_group || |
| 5303 | used_block_group->ro || | ||
| 5304 | !block_group_bits(used_block_group, data))) { | ||
| 5305 | used_block_group = block_group; | ||
| 5306 | goto refill_cluster; | 5306 | goto refill_cluster; |
| 5307 | } | ||
| 5308 | |||
| 5309 | if (used_block_group != block_group) | ||
| 5310 | btrfs_get_block_group(used_block_group); | ||
| 5307 | 5311 | ||
| 5308 | offset = btrfs_alloc_from_cluster(block_group, last_ptr, | 5312 | offset = btrfs_alloc_from_cluster(used_block_group, |
| 5309 | num_bytes, search_start); | 5313 | last_ptr, num_bytes, used_block_group->key.objectid); |
| 5310 | if (offset) { | 5314 | if (offset) { |
| 5311 | /* we have a block, we're done */ | 5315 | /* we have a block, we're done */ |
| 5312 | spin_unlock(&last_ptr->refill_lock); | 5316 | spin_unlock(&last_ptr->refill_lock); |
| 5313 | goto checks; | 5317 | goto checks; |
| 5314 | } | 5318 | } |
| 5315 | 5319 | ||
| 5316 | spin_lock(&last_ptr->lock); | 5320 | WARN_ON(last_ptr->block_group != used_block_group); |
| 5317 | /* | 5321 | if (used_block_group != block_group) { |
| 5318 | * whoops, this cluster doesn't actually point to | 5322 | btrfs_put_block_group(used_block_group); |
| 5319 | * this block group. Get a ref on the block | 5323 | used_block_group = block_group; |
| 5320 | * group is does point to and try again | ||
| 5321 | */ | ||
| 5322 | if (!last_ptr_loop && last_ptr->block_group && | ||
| 5323 | last_ptr->block_group != block_group && | ||
| 5324 | index <= | ||
| 5325 | get_block_group_index(last_ptr->block_group)) { | ||
| 5326 | |||
| 5327 | btrfs_put_block_group(block_group); | ||
| 5328 | block_group = last_ptr->block_group; | ||
| 5329 | btrfs_get_block_group(block_group); | ||
| 5330 | spin_unlock(&last_ptr->lock); | ||
| 5331 | spin_unlock(&last_ptr->refill_lock); | ||
| 5332 | |||
| 5333 | last_ptr_loop = 1; | ||
| 5334 | search_start = block_group->key.objectid; | ||
| 5335 | /* | ||
| 5336 | * we know this block group is properly | ||
| 5337 | * in the list because | ||
| 5338 | * btrfs_remove_block_group, drops the | ||
| 5339 | * cluster before it removes the block | ||
| 5340 | * group from the list | ||
| 5341 | */ | ||
| 5342 | goto have_block_group; | ||
| 5343 | } | 5324 | } |
| 5344 | spin_unlock(&last_ptr->lock); | ||
| 5345 | refill_cluster: | 5325 | refill_cluster: |
| 5326 | BUG_ON(used_block_group != block_group); | ||
| 5327 | /* If we are on LOOP_NO_EMPTY_SIZE, we can't | ||
| 5328 | * set up a new clusters, so lets just skip it | ||
| 5329 | * and let the allocator find whatever block | ||
| 5330 | * it can find. If we reach this point, we | ||
| 5331 | * will have tried the cluster allocator | ||
| 5332 | * plenty of times and not have found | ||
| 5333 | * anything, so we are likely way too | ||
| 5334 | * fragmented for the clustering stuff to find | ||
| 5335 | * anything. */ | ||
| 5336 | if (loop >= LOOP_NO_EMPTY_SIZE) { | ||
| 5337 | spin_unlock(&last_ptr->refill_lock); | ||
| 5338 | goto unclustered_alloc; | ||
| 5339 | } | ||
| 5340 | |||
| 5346 | /* | 5341 | /* |
| 5347 | * this cluster didn't work out, free it and | 5342 | * this cluster didn't work out, free it and |
| 5348 | * start over | 5343 | * start over |
| 5349 | */ | 5344 | */ |
| 5350 | btrfs_return_cluster_to_free_space(NULL, last_ptr); | 5345 | btrfs_return_cluster_to_free_space(NULL, last_ptr); |
| 5351 | 5346 | ||
| 5352 | last_ptr_loop = 0; | ||
| 5353 | |||
| 5354 | /* allocate a cluster in this block group */ | 5347 | /* allocate a cluster in this block group */ |
| 5355 | ret = btrfs_find_space_cluster(trans, root, | 5348 | ret = btrfs_find_space_cluster(trans, root, |
| 5356 | block_group, last_ptr, | 5349 | block_group, last_ptr, |
| @@ -5390,6 +5383,7 @@ refill_cluster: | |||
| 5390 | goto loop; | 5383 | goto loop; |
| 5391 | } | 5384 | } |
| 5392 | 5385 | ||
| 5386 | unclustered_alloc: | ||
| 5393 | offset = btrfs_find_space_for_alloc(block_group, search_start, | 5387 | offset = btrfs_find_space_for_alloc(block_group, search_start, |
| 5394 | num_bytes, empty_size); | 5388 | num_bytes, empty_size); |
| 5395 | /* | 5389 | /* |
| @@ -5416,14 +5410,14 @@ checks: | |||
| 5416 | search_start = stripe_align(root, offset); | 5410 | search_start = stripe_align(root, offset); |
| 5417 | /* move on to the next group */ | 5411 | /* move on to the next group */ |
| 5418 | if (search_start + num_bytes >= search_end) { | 5412 | if (search_start + num_bytes >= search_end) { |
| 5419 | btrfs_add_free_space(block_group, offset, num_bytes); | 5413 | btrfs_add_free_space(used_block_group, offset, num_bytes); |
| 5420 | goto loop; | 5414 | goto loop; |
| 5421 | } | 5415 | } |
| 5422 | 5416 | ||
| 5423 | /* move on to the next group */ | 5417 | /* move on to the next group */ |
| 5424 | if (search_start + num_bytes > | 5418 | if (search_start + num_bytes > |
| 5425 | block_group->key.objectid + block_group->key.offset) { | 5419 | used_block_group->key.objectid + used_block_group->key.offset) { |
| 5426 | btrfs_add_free_space(block_group, offset, num_bytes); | 5420 | btrfs_add_free_space(used_block_group, offset, num_bytes); |
| 5427 | goto loop; | 5421 | goto loop; |
| 5428 | } | 5422 | } |
| 5429 | 5423 | ||
| @@ -5431,14 +5425,14 @@ checks: | |||
| 5431 | ins->offset = num_bytes; | 5425 | ins->offset = num_bytes; |
| 5432 | 5426 | ||
| 5433 | if (offset < search_start) | 5427 | if (offset < search_start) |
| 5434 | btrfs_add_free_space(block_group, offset, | 5428 | btrfs_add_free_space(used_block_group, offset, |
| 5435 | search_start - offset); | 5429 | search_start - offset); |
| 5436 | BUG_ON(offset > search_start); | 5430 | BUG_ON(offset > search_start); |
| 5437 | 5431 | ||
| 5438 | ret = btrfs_update_reserved_bytes(block_group, num_bytes, | 5432 | ret = btrfs_update_reserved_bytes(used_block_group, num_bytes, |
| 5439 | alloc_type); | 5433 | alloc_type); |
| 5440 | if (ret == -EAGAIN) { | 5434 | if (ret == -EAGAIN) { |
| 5441 | btrfs_add_free_space(block_group, offset, num_bytes); | 5435 | btrfs_add_free_space(used_block_group, offset, num_bytes); |
| 5442 | goto loop; | 5436 | goto loop; |
| 5443 | } | 5437 | } |
| 5444 | 5438 | ||
| @@ -5447,15 +5441,19 @@ checks: | |||
| 5447 | ins->offset = num_bytes; | 5441 | ins->offset = num_bytes; |
| 5448 | 5442 | ||
| 5449 | if (offset < search_start) | 5443 | if (offset < search_start) |
| 5450 | btrfs_add_free_space(block_group, offset, | 5444 | btrfs_add_free_space(used_block_group, offset, |
| 5451 | search_start - offset); | 5445 | search_start - offset); |
| 5452 | BUG_ON(offset > search_start); | 5446 | BUG_ON(offset > search_start); |
| 5447 | if (used_block_group != block_group) | ||
| 5448 | btrfs_put_block_group(used_block_group); | ||
| 5453 | btrfs_put_block_group(block_group); | 5449 | btrfs_put_block_group(block_group); |
| 5454 | break; | 5450 | break; |
| 5455 | loop: | 5451 | loop: |
| 5456 | failed_cluster_refill = false; | 5452 | failed_cluster_refill = false; |
| 5457 | failed_alloc = false; | 5453 | failed_alloc = false; |
| 5458 | BUG_ON(index != get_block_group_index(block_group)); | 5454 | BUG_ON(index != get_block_group_index(block_group)); |
| 5455 | if (used_block_group != block_group) | ||
| 5456 | btrfs_put_block_group(used_block_group); | ||
| 5459 | btrfs_put_block_group(block_group); | 5457 | btrfs_put_block_group(block_group); |
| 5460 | } | 5458 | } |
| 5461 | up_read(&space_info->groups_sem); | 5459 | up_read(&space_info->groups_sem); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index be1bf627a14b..49f3c9dc09f4 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -935,8 +935,10 @@ again: | |||
| 935 | node = tree_search(tree, start); | 935 | node = tree_search(tree, start); |
| 936 | if (!node) { | 936 | if (!node) { |
| 937 | prealloc = alloc_extent_state_atomic(prealloc); | 937 | prealloc = alloc_extent_state_atomic(prealloc); |
| 938 | if (!prealloc) | 938 | if (!prealloc) { |
| 939 | return -ENOMEM; | 939 | err = -ENOMEM; |
| 940 | goto out; | ||
| 941 | } | ||
| 940 | err = insert_state(tree, prealloc, start, end, &bits); | 942 | err = insert_state(tree, prealloc, start, end, &bits); |
| 941 | prealloc = NULL; | 943 | prealloc = NULL; |
| 942 | BUG_ON(err == -EEXIST); | 944 | BUG_ON(err == -EEXIST); |
| @@ -992,8 +994,10 @@ hit_next: | |||
| 992 | */ | 994 | */ |
| 993 | if (state->start < start) { | 995 | if (state->start < start) { |
| 994 | prealloc = alloc_extent_state_atomic(prealloc); | 996 | prealloc = alloc_extent_state_atomic(prealloc); |
| 995 | if (!prealloc) | 997 | if (!prealloc) { |
| 996 | return -ENOMEM; | 998 | err = -ENOMEM; |
| 999 | goto out; | ||
| 1000 | } | ||
| 997 | err = split_state(tree, state, prealloc, start); | 1001 | err = split_state(tree, state, prealloc, start); |
| 998 | BUG_ON(err == -EEXIST); | 1002 | BUG_ON(err == -EEXIST); |
| 999 | prealloc = NULL; | 1003 | prealloc = NULL; |
| @@ -1024,8 +1028,10 @@ hit_next: | |||
| 1024 | this_end = last_start - 1; | 1028 | this_end = last_start - 1; |
| 1025 | 1029 | ||
| 1026 | prealloc = alloc_extent_state_atomic(prealloc); | 1030 | prealloc = alloc_extent_state_atomic(prealloc); |
| 1027 | if (!prealloc) | 1031 | if (!prealloc) { |
| 1028 | return -ENOMEM; | 1032 | err = -ENOMEM; |
| 1033 | goto out; | ||
| 1034 | } | ||
| 1029 | 1035 | ||
| 1030 | /* | 1036 | /* |
| 1031 | * Avoid to free 'prealloc' if it can be merged with | 1037 | * Avoid to free 'prealloc' if it can be merged with |
| @@ -1051,8 +1057,10 @@ hit_next: | |||
| 1051 | */ | 1057 | */ |
| 1052 | if (state->start <= end && state->end > end) { | 1058 | if (state->start <= end && state->end > end) { |
| 1053 | prealloc = alloc_extent_state_atomic(prealloc); | 1059 | prealloc = alloc_extent_state_atomic(prealloc); |
| 1054 | if (!prealloc) | 1060 | if (!prealloc) { |
| 1055 | return -ENOMEM; | 1061 | err = -ENOMEM; |
| 1062 | goto out; | ||
| 1063 | } | ||
| 1056 | 1064 | ||
| 1057 | err = split_state(tree, state, prealloc, end + 1); | 1065 | err = split_state(tree, state, prealloc, end + 1); |
| 1058 | BUG_ON(err == -EEXIST); | 1066 | BUG_ON(err == -EEXIST); |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index c37433d3cd82..0a8c8f8304b1 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -1611,7 +1611,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
| 1611 | if ((sb->s_flags & MS_RDONLY) && !root->fs_info->fs_devices->seeding) | 1611 | if ((sb->s_flags & MS_RDONLY) && !root->fs_info->fs_devices->seeding) |
| 1612 | return -EINVAL; | 1612 | return -EINVAL; |
| 1613 | 1613 | ||
| 1614 | bdev = blkdev_get_by_path(device_path, FMODE_EXCL, | 1614 | bdev = blkdev_get_by_path(device_path, FMODE_WRITE | FMODE_EXCL, |
| 1615 | root->fs_info->bdev_holder); | 1615 | root->fs_info->bdev_holder); |
| 1616 | if (IS_ERR(bdev)) | 1616 | if (IS_ERR(bdev)) |
| 1617 | return PTR_ERR(bdev); | 1617 | return PTR_ERR(bdev); |
