|
@@ -168,11 +168,13 @@ static u64 find_search_start(struct btrfs_root *root,
|
|
u64 last;
|
|
u64 last;
|
|
u64 start = 0;
|
|
u64 start = 0;
|
|
u64 end = 0;
|
|
u64 end = 0;
|
|
|
|
+ int wrapped = 0;
|
|
|
|
|
|
again:
|
|
again:
|
|
ret = cache_block_group(root, cache);
|
|
ret = cache_block_group(root, cache);
|
|
if (ret)
|
|
if (ret)
|
|
goto out;
|
|
goto out;
|
|
|
|
+
|
|
last = max(search_start, cache->key.objectid);
|
|
last = max(search_start, cache->key.objectid);
|
|
|
|
|
|
while(1) {
|
|
while(1) {
|
|
@@ -195,8 +197,15 @@ out:
|
|
|
|
|
|
new_group:
|
|
new_group:
|
|
last = cache->key.objectid + cache->key.offset;
|
|
last = cache->key.objectid + cache->key.offset;
|
|
|
|
+wrapped:
|
|
cache = btrfs_lookup_block_group(root->fs_info, last);
|
|
cache = btrfs_lookup_block_group(root->fs_info, last);
|
|
if (!cache) {
|
|
if (!cache) {
|
|
|
|
+ if (!wrapped) {
|
|
|
|
+ wrapped = 1;
|
|
|
|
+ last = search_start;
|
|
|
|
+ data = BTRFS_BLOCK_GROUP_MIXED;
|
|
|
|
+ goto wrapped;
|
|
|
|
+ }
|
|
return search_start;
|
|
return search_start;
|
|
}
|
|
}
|
|
cache = btrfs_find_block_group(root, cache, last, data, 0);
|
|
cache = btrfs_find_block_group(root, cache, last, data, 0);
|
|
@@ -236,9 +245,11 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
|
|
block_group_cache = &info->block_group_cache;
|
|
block_group_cache = &info->block_group_cache;
|
|
|
|
|
|
if (!owner)
|
|
if (!owner)
|
|
- factor = 5;
|
|
|
|
|
|
+ factor = 8;
|
|
|
|
|
|
- if (data)
|
|
|
|
|
|
+ if (data == BTRFS_BLOCK_GROUP_MIXED)
|
|
|
|
+ bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA;
|
|
|
|
+ else if (data)
|
|
bit = BLOCK_GROUP_DATA;
|
|
bit = BLOCK_GROUP_DATA;
|
|
else
|
|
else
|
|
bit = BLOCK_GROUP_METADATA;
|
|
bit = BLOCK_GROUP_METADATA;
|
|
@@ -246,14 +257,16 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
|
|
if (search_start) {
|
|
if (search_start) {
|
|
struct btrfs_block_group_cache *shint;
|
|
struct btrfs_block_group_cache *shint;
|
|
shint = btrfs_lookup_block_group(info, search_start);
|
|
shint = btrfs_lookup_block_group(info, search_start);
|
|
- if (shint && shint->data == data) {
|
|
|
|
|
|
+ if (shint && (shint->data == data ||
|
|
|
|
+ shint->data == BTRFS_BLOCK_GROUP_MIXED)) {
|
|
used = btrfs_block_group_used(&shint->item);
|
|
used = btrfs_block_group_used(&shint->item);
|
|
if (used < div_factor(shint->key.offset, factor)) {
|
|
if (used < div_factor(shint->key.offset, factor)) {
|
|
return shint;
|
|
return shint;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if (hint && hint->data == data) {
|
|
|
|
|
|
+ if (hint && (hint->data == data ||
|
|
|
|
+ hint->data == BTRFS_BLOCK_GROUP_MIXED)) {
|
|
used = btrfs_block_group_used(&hint->item);
|
|
used = btrfs_block_group_used(&hint->item);
|
|
if (used < div_factor(hint->key.offset, factor)) {
|
|
if (used < div_factor(hint->key.offset, factor)) {
|
|
return hint;
|
|
return hint;
|
|
@@ -592,11 +605,15 @@ static int update_block_group(struct btrfs_trans_handle *trans,
|
|
if (data) {
|
|
if (data) {
|
|
bit_to_clear = BLOCK_GROUP_METADATA;
|
|
bit_to_clear = BLOCK_GROUP_METADATA;
|
|
bit_to_set = BLOCK_GROUP_DATA;
|
|
bit_to_set = BLOCK_GROUP_DATA;
|
|
|
|
+ cache->item.flags &=
|
|
|
|
+ ~BTRFS_BLOCK_GROUP_MIXED;
|
|
cache->item.flags |=
|
|
cache->item.flags |=
|
|
BTRFS_BLOCK_GROUP_DATA;
|
|
BTRFS_BLOCK_GROUP_DATA;
|
|
} else {
|
|
} else {
|
|
bit_to_clear = BLOCK_GROUP_DATA;
|
|
bit_to_clear = BLOCK_GROUP_DATA;
|
|
bit_to_set = BLOCK_GROUP_METADATA;
|
|
bit_to_set = BLOCK_GROUP_METADATA;
|
|
|
|
+ cache->item.flags &=
|
|
|
|
+ ~BTRFS_BLOCK_GROUP_MIXED;
|
|
cache->item.flags &=
|
|
cache->item.flags &=
|
|
~BTRFS_BLOCK_GROUP_DATA;
|
|
~BTRFS_BLOCK_GROUP_DATA;
|
|
}
|
|
}
|
|
@@ -606,6 +623,14 @@ static int update_block_group(struct btrfs_trans_handle *trans,
|
|
set_extent_bits(&info->block_group_cache,
|
|
set_extent_bits(&info->block_group_cache,
|
|
start, end, bit_to_set,
|
|
start, end, bit_to_set,
|
|
GFP_NOFS);
|
|
GFP_NOFS);
|
|
|
|
+ } else if (cache->data != data &&
|
|
|
|
+ cache->data != BTRFS_BLOCK_GROUP_MIXED) {
|
|
|
|
+ cache->data = BTRFS_BLOCK_GROUP_MIXED;
|
|
|
|
+ set_extent_bits(&info->block_group_cache,
|
|
|
|
+ start, end,
|
|
|
|
+ BLOCK_GROUP_DATA |
|
|
|
|
+ BLOCK_GROUP_METADATA,
|
|
|
|
+ GFP_NOFS);
|
|
}
|
|
}
|
|
old_val += num_bytes;
|
|
old_val += num_bytes;
|
|
} else {
|
|
} else {
|
|
@@ -886,6 +911,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
|
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;
|
|
|
|
+ u64 cached_start;
|
|
|
|
|
|
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);
|
|
@@ -910,6 +936,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
|
check_failed:
|
|
check_failed:
|
|
search_start = find_search_start(root, &block_group,
|
|
search_start = find_search_start(root, &block_group,
|
|
search_start, total_needed, data);
|
|
search_start, total_needed, data);
|
|
|
|
+ cached_start = search_start;
|
|
btrfs_init_path(path);
|
|
btrfs_init_path(path);
|
|
ins->objectid = search_start;
|
|
ins->objectid = search_start;
|
|
ins->offset = 0;
|
|
ins->offset = 0;
|
|
@@ -1532,9 +1559,12 @@ int btrfs_read_block_groups(struct btrfs_root *root)
|
|
key.objectid = found_key.objectid + found_key.offset;
|
|
key.objectid = found_key.objectid + found_key.offset;
|
|
btrfs_release_path(root, path);
|
|
btrfs_release_path(root, path);
|
|
|
|
|
|
- if (cache->item.flags & BTRFS_BLOCK_GROUP_DATA) {
|
|
|
|
|
|
+ if (cache->item.flags & BTRFS_BLOCK_GROUP_MIXED) {
|
|
|
|
+ bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA;
|
|
|
|
+ cache->data = BTRFS_BLOCK_GROUP_MIXED;
|
|
|
|
+ } else if (cache->item.flags & BTRFS_BLOCK_GROUP_DATA) {
|
|
bit = BLOCK_GROUP_DATA;
|
|
bit = BLOCK_GROUP_DATA;
|
|
- cache->data = 1;
|
|
|
|
|
|
+ cache->data = BTRFS_BLOCK_GROUP_DATA;
|
|
} else {
|
|
} else {
|
|
bit = BLOCK_GROUP_METADATA;
|
|
bit = BLOCK_GROUP_METADATA;
|
|
cache->data = 0;
|
|
cache->data = 0;
|