Commit f2654de4 authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse

Btrfs: Allow find_free_extent callers to pass in an exclusion range

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 4b52dff6
...@@ -25,7 +25,8 @@ ...@@ -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, ...@@ -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, ...@@ -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 ...@@ -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 ...@@ -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 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1191,6 +1194,11 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
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, ...@@ -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,33 +1308,19 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, ...@@ -1298,33 +1308,19 @@ 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) { if (ret)
return ret; return ret;
} exclude_nr = info->extent_tree_prealloc_nr;
if (prealloc_key.objectid + prealloc_key.offset >= search_end) { exclude_start = info->extent_tree_prealloc[exclude_nr - 1];
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 */ /* do the real allocation */
ret = find_free_extent(trans, root, num_blocks, search_start, ret = find_free_extent(trans, root, num_blocks, search_start,
search_end, hint_block, ins, data); search_end, hint_block, ins,
if (ret) { exclude_start, exclude_nr, data);
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, num_blocks, search_start,
search_end, hint_block, ins, 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
...@@ -1336,29 +1332,14 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment