|
@@ -1473,13 +1473,31 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
|
|
struct btrfs_root * root = orig_root->fs_info->extent_root;
|
|
struct btrfs_root * root = orig_root->fs_info->extent_root;
|
|
struct btrfs_fs_info *info = root->fs_info;
|
|
struct btrfs_fs_info *info = root->fs_info;
|
|
u64 total_needed = num_bytes;
|
|
u64 total_needed = num_bytes;
|
|
|
|
+ u64 *last_ptr = NULL;
|
|
struct btrfs_block_group_cache *block_group;
|
|
struct btrfs_block_group_cache *block_group;
|
|
int full_scan = 0;
|
|
int full_scan = 0;
|
|
int wrapped = 0;
|
|
int wrapped = 0;
|
|
|
|
+ int empty_cluster = 2 * 1024 * 1024;
|
|
|
|
|
|
WARN_ON(num_bytes < root->sectorsize);
|
|
WARN_ON(num_bytes < root->sectorsize);
|
|
btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
|
|
btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
|
|
|
|
|
|
|
|
+ if (data & BTRFS_BLOCK_GROUP_METADATA) {
|
|
|
|
+ last_ptr = &root->fs_info->last_alloc;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD)) {
|
|
|
|
+ last_ptr = &root->fs_info->last_data_alloc;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (last_ptr) {
|
|
|
|
+ if (*last_ptr)
|
|
|
|
+ hint_byte = *last_ptr;
|
|
|
|
+ else {
|
|
|
|
+ empty_size += empty_cluster;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
if (search_end == (u64)-1)
|
|
if (search_end == (u64)-1)
|
|
search_end = btrfs_super_total_bytes(&info->super_copy);
|
|
search_end = btrfs_super_total_bytes(&info->super_copy);
|
|
|
|
|
|
@@ -1489,11 +1507,14 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
|
|
hint_byte = search_start;
|
|
hint_byte = search_start;
|
|
block_group = btrfs_find_block_group(root, block_group,
|
|
block_group = btrfs_find_block_group(root, block_group,
|
|
hint_byte, data, 1);
|
|
hint_byte, data, 1);
|
|
|
|
+ if (last_ptr && *last_ptr == 0 && block_group)
|
|
|
|
+ hint_byte = block_group->key.objectid;
|
|
} else {
|
|
} else {
|
|
block_group = btrfs_find_block_group(root,
|
|
block_group = btrfs_find_block_group(root,
|
|
trans->block_group,
|
|
trans->block_group,
|
|
search_start, data, 1);
|
|
search_start, data, 1);
|
|
}
|
|
}
|
|
|
|
+ search_start = max(search_start, hint_byte);
|
|
|
|
|
|
total_needed += empty_size;
|
|
total_needed += empty_size;
|
|
|
|
|
|
@@ -1506,9 +1527,36 @@ check_failed:
|
|
}
|
|
}
|
|
ret = find_search_start(root, &block_group, &search_start,
|
|
ret = find_search_start(root, &block_group, &search_start,
|
|
total_needed, data);
|
|
total_needed, data);
|
|
|
|
+ if (ret == -ENOSPC && last_ptr && *last_ptr) {
|
|
|
|
+ *last_ptr = 0;
|
|
|
|
+ block_group = btrfs_lookup_block_group(info,
|
|
|
|
+ orig_search_start);
|
|
|
|
+ search_start = orig_search_start;
|
|
|
|
+ ret = find_search_start(root, &block_group, &search_start,
|
|
|
|
+ total_needed, data);
|
|
|
|
+ }
|
|
|
|
+ if (ret == -ENOSPC)
|
|
|
|
+ goto enospc;
|
|
if (ret)
|
|
if (ret)
|
|
goto error;
|
|
goto error;
|
|
|
|
|
|
|
|
+ if (last_ptr && *last_ptr && search_start != *last_ptr) {
|
|
|
|
+ *last_ptr = 0;
|
|
|
|
+ if (!empty_size) {
|
|
|
|
+ empty_size += empty_cluster;
|
|
|
|
+ total_needed += empty_size;
|
|
|
|
+ }
|
|
|
|
+ block_group = btrfs_lookup_block_group(info,
|
|
|
|
+ orig_search_start);
|
|
|
|
+ search_start = orig_search_start;
|
|
|
|
+ ret = find_search_start(root, &block_group,
|
|
|
|
+ &search_start, total_needed, data);
|
|
|
|
+ if (ret == -ENOSPC)
|
|
|
|
+ goto enospc;
|
|
|
|
+ if (ret)
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+
|
|
search_start = stripe_align(root, search_start);
|
|
search_start = stripe_align(root, search_start);
|
|
ins->objectid = search_start;
|
|
ins->objectid = search_start;
|
|
ins->offset = num_bytes;
|
|
ins->offset = num_bytes;
|
|
@@ -1547,6 +1595,13 @@ check_failed:
|
|
trans->block_group = block_group;
|
|
trans->block_group = block_group;
|
|
}
|
|
}
|
|
ins->offset = num_bytes;
|
|
ins->offset = num_bytes;
|
|
|
|
+ if (last_ptr) {
|
|
|
|
+ *last_ptr = ins->objectid + ins->offset;
|
|
|
|
+ if (*last_ptr ==
|
|
|
|
+ btrfs_super_total_bytes(&root->fs_info->super_copy)) {
|
|
|
|
+ *last_ptr = 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
new_group:
|
|
new_group:
|
|
@@ -1612,12 +1667,12 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
|
|
if (root->ref_cows) {
|
|
if (root->ref_cows) {
|
|
if (data != BTRFS_BLOCK_GROUP_METADATA) {
|
|
if (data != BTRFS_BLOCK_GROUP_METADATA) {
|
|
ret = do_chunk_alloc(trans, root->fs_info->extent_root,
|
|
ret = do_chunk_alloc(trans, root->fs_info->extent_root,
|
|
- num_bytes,
|
|
|
|
|
|
+ 2 * 1024 * 1024,
|
|
BTRFS_BLOCK_GROUP_METADATA);
|
|
BTRFS_BLOCK_GROUP_METADATA);
|
|
BUG_ON(ret);
|
|
BUG_ON(ret);
|
|
}
|
|
}
|
|
ret = do_chunk_alloc(trans, root->fs_info->extent_root,
|
|
ret = do_chunk_alloc(trans, root->fs_info->extent_root,
|
|
- num_bytes, data);
|
|
|
|
|
|
+ num_bytes + 2 * 1024 * 1024, data);
|
|
BUG_ON(ret);
|
|
BUG_ON(ret);
|
|
}
|
|
}
|
|
|
|
|