summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-06-26 18:20:46 +0200
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-06-26 18:20:46 +0200
commitf2654de42a759127cb1f1e8a626ec94178732e20 (patch)
tree27a4b6ab03a775241d5a80f98139cf17c1fef6f3
parentBtrfs: Fix super block updates during transaction commit (diff)
downloadlinux-f2654de42a759127cb1f1e8a626ec94178732e20.tar.xz
linux-f2654de42a759127cb1f1e8a626ec94178732e20.zip
Btrfs: Allow find_free_extent callers to pass in an exclusion range
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/extent-tree.c79
1 files changed, 30 insertions, 49 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 7e550343aee7..01dc30579287 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -25,7 +25,8 @@
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*orig_root, u64 num_blocks, u64 search_start,
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
btrfs_root *extent_root);
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)
return -ENOMEM;
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) {
btrfs_free_path(path);
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_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 */
if (ret)
return ret;
@@ -868,7 +870,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
if (!path)
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) {
btrfs_free_path(path);
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
*orig_root, u64 num_blocks, u64 search_start, u64
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_key key;
@@ -1191,6 +1194,11 @@ check_pending:
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) {
int nr;
test_block = ins->objectid;
@@ -1267,6 +1275,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
int pending_ret;
u64 super_blocks_used;
u64 search_start = 0;
+ u64 exclude_start = 0;
+ u64 exclude_nr = 0;
struct btrfs_fs_info *info = root->fs_info;
struct btrfs_root *extent_root = info->extent_root;
struct btrfs_extent_item extent_item;
@@ -1298,33 +1308,19 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
*/
if (data) {
ret = find_free_extent(trans, root, 0, 0,
- search_end, 0, &prealloc_key, 0);
- if (ret) {
+ 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;
- }
+ exclude_nr = info->extent_tree_prealloc_nr;
+ exclude_start = info->extent_tree_prealloc[exclude_nr - 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)
- return ret;
- }
+ 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
@@ -1336,29 +1332,14 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
* The unused prealloc will get reused the next time around.
*/
if (!data) {
- if (ins->objectid + ins->offset >= search_end)
- search_end = ins->objectid - 1;
- else
- search_start = ins->objectid + ins->offset;
-
- if (hint_block < search_start)
- hint_block = search_start;
-
+ exclude_start = ins->objectid;
+ exclude_nr = ins->offset;
ret = find_free_extent(trans, root, 0, search_start,
search_end, hint_block,
- &prealloc_key, 0);
- 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, 0, search_start,
- search_end, hint_block,
- &prealloc_key, 0);
- if (ret)
- return ret;
- }
+ &prealloc_key, exclude_start,
+ exclude_nr, 0);
+ if (ret)
+ return ret;
}
super_blocks_used = btrfs_super_blocks_used(&info->super_copy);