Btrfs: Allow find_free_extent callers to pass in an exclusion range
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
committed by
David Woodhouse
parent
4b52dff6d3
commit
f2654de42a
@@ -25,7 +25,8 @@
|
|||||||
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
*orig_root, u64 num_blocks, u64 search_start,
|
*orig_root, u64 num_blocks, u64 search_start,
|
||||||
u64 search_end, u64 hint_block,
|
u64 search_end, u64 hint_block,
|
||||||
struct btrfs_key *ins, int data);
|
struct btrfs_key *ins, u64 exclude_start,
|
||||||
|
u64 exclude_nr, int data);
|
||||||
static int finish_current_insert(struct btrfs_trans_handle *trans, struct
|
static int finish_current_insert(struct btrfs_trans_handle *trans, struct
|
||||||
btrfs_root *extent_root);
|
btrfs_root *extent_root);
|
||||||
static int del_pending_extents(struct btrfs_trans_handle *trans, struct
|
static int del_pending_extents(struct btrfs_trans_handle *trans, struct
|
||||||
@@ -407,7 +408,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
|
|||||||
if (!path)
|
if (!path)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
ret = find_free_extent(trans, root->fs_info->extent_root, 0, 0,
|
ret = find_free_extent(trans, root->fs_info->extent_root, 0, 0,
|
||||||
(u64)-1, 0, &ins, 0);
|
(u64)-1, 0, &ins, 0, 0, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -559,7 +560,8 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
|
|||||||
struct btrfs_block_group_item *bi;
|
struct btrfs_block_group_item *bi;
|
||||||
struct btrfs_key ins;
|
struct btrfs_key ins;
|
||||||
|
|
||||||
ret = find_free_extent(trans, extent_root, 0, 0, (u64)-1, 0, &ins, 0);
|
ret = find_free_extent(trans, extent_root, 0, 0, (u64)-1, 0, &ins,
|
||||||
|
0, 0, 0);
|
||||||
/* FIXME, set bit to recalc cache groups on next mount */
|
/* FIXME, set bit to recalc cache groups on next mount */
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -868,7 +870,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
|||||||
if (!path)
|
if (!path)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = find_free_extent(trans, root, 0, 0, (u64)-1, 0, &ins, 0);
|
ret = find_free_extent(trans, root, 0, 0, (u64)-1, 0, &ins, 0, 0, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -987,7 +989,8 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
|||||||
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
*orig_root, u64 num_blocks, u64 search_start, u64
|
*orig_root, u64 num_blocks, u64 search_start, u64
|
||||||
search_end, u64 hint_block,
|
search_end, u64 hint_block,
|
||||||
struct btrfs_key *ins, int data)
|
struct btrfs_key *ins, u64 exclude_start,
|
||||||
|
u64 exclude_nr, int data)
|
||||||
{
|
{
|
||||||
struct btrfs_path *path;
|
struct btrfs_path *path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@@ -1191,6 +1194,11 @@ check_pending:
|
|||||||
goto new_group;
|
goto new_group;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (exclude_nr > 0 && (ins->objectid + num_blocks > exclude_start &&
|
||||||
|
ins->objectid < exclude_start + exclude_nr)) {
|
||||||
|
search_start = exclude_start + exclude_nr;
|
||||||
|
goto new_group;
|
||||||
|
}
|
||||||
if (fill_prealloc) {
|
if (fill_prealloc) {
|
||||||
int nr;
|
int nr;
|
||||||
test_block = ins->objectid;
|
test_block = ins->objectid;
|
||||||
@@ -1267,6 +1275,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
|
|||||||
int pending_ret;
|
int pending_ret;
|
||||||
u64 super_blocks_used;
|
u64 super_blocks_used;
|
||||||
u64 search_start = 0;
|
u64 search_start = 0;
|
||||||
|
u64 exclude_start = 0;
|
||||||
|
u64 exclude_nr = 0;
|
||||||
struct btrfs_fs_info *info = root->fs_info;
|
struct btrfs_fs_info *info = root->fs_info;
|
||||||
struct btrfs_root *extent_root = info->extent_root;
|
struct btrfs_root *extent_root = info->extent_root;
|
||||||
struct btrfs_extent_item extent_item;
|
struct btrfs_extent_item extent_item;
|
||||||
@@ -1298,34 +1308,20 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
|
|||||||
*/
|
*/
|
||||||
if (data) {
|
if (data) {
|
||||||
ret = find_free_extent(trans, root, 0, 0,
|
ret = find_free_extent(trans, root, 0, 0,
|
||||||
search_end, 0, &prealloc_key, 0);
|
search_end, 0, &prealloc_key, 0, 0, 0);
|
||||||
if (ret) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (prealloc_key.objectid + prealloc_key.offset >= search_end) {
|
|
||||||
int nr = info->extent_tree_prealloc_nr;
|
|
||||||
search_end = info->extent_tree_prealloc[nr - 1] - 1;
|
|
||||||
} else {
|
|
||||||
search_start = info->extent_tree_prealloc[0] + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hint_block < search_start)
|
|
||||||
hint_block = search_start;
|
|
||||||
/* do the real allocation */
|
|
||||||
ret = find_free_extent(trans, root, num_blocks, search_start,
|
|
||||||
search_end, hint_block, ins, data);
|
|
||||||
if (ret) {
|
|
||||||
if (search_start == 0)
|
|
||||||
return ret;
|
|
||||||
search_end = search_start - 1;
|
|
||||||
search_start = 0;
|
|
||||||
hint_block = search_start;
|
|
||||||
ret = find_free_extent(trans, root, num_blocks, search_start,
|
|
||||||
search_end, hint_block, ins, data);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
exclude_nr = info->extent_tree_prealloc_nr;
|
||||||
|
exclude_start = info->extent_tree_prealloc[exclude_nr - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* do the real allocation */
|
||||||
|
ret = find_free_extent(trans, root, num_blocks, search_start,
|
||||||
|
search_end, hint_block, ins,
|
||||||
|
exclude_start, exclude_nr, data);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if we're doing a metadata allocation, preallocate space in the
|
* if we're doing a metadata allocation, preallocate space in the
|
||||||
* extent tree second. This way, we don't create a tiny hole
|
* extent tree second. This way, we don't create a tiny hole
|
||||||
@@ -1336,29 +1332,14 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
|
|||||||
* The unused prealloc will get reused the next time around.
|
* The unused prealloc will get reused the next time around.
|
||||||
*/
|
*/
|
||||||
if (!data) {
|
if (!data) {
|
||||||
if (ins->objectid + ins->offset >= search_end)
|
exclude_start = ins->objectid;
|
||||||
search_end = ins->objectid - 1;
|
exclude_nr = ins->offset;
|
||||||
else
|
|
||||||
search_start = ins->objectid + ins->offset;
|
|
||||||
|
|
||||||
if (hint_block < search_start)
|
|
||||||
hint_block = search_start;
|
|
||||||
|
|
||||||
ret = find_free_extent(trans, root, 0, search_start,
|
ret = find_free_extent(trans, root, 0, search_start,
|
||||||
search_end, hint_block,
|
search_end, hint_block,
|
||||||
&prealloc_key, 0);
|
&prealloc_key, exclude_start,
|
||||||
if (ret) {
|
exclude_nr, 0);
|
||||||
if (search_start == 0)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
search_end = search_start - 1;
|
|
||||||
search_start = 0;
|
|
||||||
hint_block = search_start;
|
|
||||||
ret = find_free_extent(trans, root, 0, search_start,
|
|
||||||
search_end, hint_block,
|
|
||||||
&prealloc_key, 0);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super_blocks_used = btrfs_super_blocks_used(&info->super_copy);
|
super_blocks_used = btrfs_super_blocks_used(&info->super_copy);
|
||||||
|
Reference in New Issue
Block a user