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

Btrfs: use a separate flag for search_start vs a hint in find_free_extent

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 1e2677e0
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
#include "transaction.h" #include "transaction.h"
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,
search_end, struct btrfs_key *ins, int data); u64 search_end, u64 hint_block,
struct btrfs_key *ins, 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
...@@ -157,12 +158,6 @@ static struct btrfs_block_group_cache *lookup_block_group(struct ...@@ -157,12 +158,6 @@ static struct btrfs_block_group_cache *lookup_block_group(struct
block_group->key.objectid + block_group->key.offset) block_group->key.objectid + block_group->key.offset)
return block_group; return block_group;
} }
WARN_ON(1);
printk("lookup_block_group fails for blocknr %Lu\n", blocknr);
printk("last ret was %d\n", ret);
if (ret) {
printk("last block group was %Lu %Lu\n", block_group->key.objectid, block_group->key.offset);
}
return NULL; return NULL;
} }
...@@ -378,7 +373,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, ...@@ -378,7 +373,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
struct btrfs_key ins; struct btrfs_key ins;
u32 refs; u32 refs;
find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1, find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1, 0,
&ins, 0); &ins, 0);
path = btrfs_alloc_path(); path = btrfs_alloc_path();
BUG_ON(!path); BUG_ON(!path);
...@@ -495,7 +490,7 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans, ...@@ -495,7 +490,7 @@ 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;
find_free_extent(trans, extent_root, 0, 0, (u64)-1, &ins, 0); find_free_extent(trans, extent_root, 0, 0, (u64)-1, 0, &ins, 0);
ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1);
BUG_ON(ret); BUG_ON(ret);
bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
...@@ -788,7 +783,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -788,7 +783,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
key.offset = num_blocks; key.offset = num_blocks;
find_free_extent(trans, root, 0, 0, (u64)-1, &ins, 0); find_free_extent(trans, root, 0, 0, (u64)-1, 0, &ins, 0);
path = btrfs_alloc_path(); path = btrfs_alloc_path();
BUG_ON(!path); BUG_ON(!path);
btrfs_init_path(path); btrfs_init_path(path);
...@@ -906,7 +901,8 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -906,7 +901,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, struct btrfs_key *ins, int data) search_end, u64 hint_block,
struct btrfs_key *ins, int data)
{ {
struct btrfs_path *path; struct btrfs_path *path;
struct btrfs_key key; struct btrfs_key key;
...@@ -926,6 +922,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -926,6 +922,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
int level; int level;
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;
u64 limit; u64 limit;
path = btrfs_alloc_path(); path = btrfs_alloc_path();
...@@ -940,10 +937,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -940,10 +937,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
} }
if (search_end == (u64)-1) if (search_end == (u64)-1)
search_end = btrfs_super_total_blocks(info->disk_super); search_end = btrfs_super_total_blocks(info->disk_super);
if (search_start) { if (hint_block) {
block_group = lookup_block_group(info, search_start); block_group = lookup_block_group(info, hint_block);
block_group = btrfs_find_block_group(root, block_group, block_group = btrfs_find_block_group(root, block_group,
search_start, data, 1); hint_block, data, 1);
} else { } else {
block_group = btrfs_find_block_group(root, block_group = btrfs_find_block_group(root,
trans->block_group, 0, trans->block_group, 0,
...@@ -954,7 +951,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -954,7 +951,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
if (!block_group->data) if (!block_group->data)
search_start = find_search_start(root, &block_group, search_start = find_search_start(root, &block_group,
search_start, total_needed); search_start, total_needed);
else else if (!full_scan)
search_start = max(block_group->last_alloc, search_start); search_start = max(block_group->last_alloc, search_start);
btrfs_init_path(path); btrfs_init_path(path);
...@@ -1039,7 +1036,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1039,7 +1036,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
start_found = 1; start_found = 1;
last_block = key.objectid + key.offset; last_block = key.objectid + key.offset;
if (last_block >= block_group->key.objectid + if (!full_scan && last_block >= block_group->key.objectid +
block_group->key.offset) { block_group->key.offset) {
btrfs_release_path(root, path); btrfs_release_path(root, path);
search_start = block_group->key.objectid + search_start = block_group->key.objectid +
...@@ -1059,10 +1056,15 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1059,10 +1056,15 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
BUG_ON(ins->objectid < search_start); BUG_ON(ins->objectid < search_start);
if (ins->objectid + num_blocks >= search_end) { if (ins->objectid + num_blocks >= search_end) {
if (full_scan) if (full_scan) {
return -ENOSPC; ret = -ENOSPC;
goto error;
}
search_start = orig_search_start; search_start = orig_search_start;
full_scan = 1; if (wrapped)
full_scan = 1;
else
wrapped = 1;
goto new_group; goto new_group;
} }
for (test_block = ins->objectid; for (test_block = ins->objectid;
...@@ -1132,14 +1134,20 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1132,14 +1134,20 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
new_group: new_group:
if (search_start + num_blocks >= search_end) { if (search_start + num_blocks >= search_end) {
search_start = orig_search_start; search_start = orig_search_start;
printk("doing full scan!\n"); if (full_scan) {
full_scan = 1; ret = -ENOSPC;
goto error;
}
if (wrapped)
full_scan = 1;
else
wrapped = 1;
} }
block_group = lookup_block_group(info, search_start); block_group = lookup_block_group(info, search_start);
cond_resched();
if (!full_scan) if (!full_scan)
block_group = btrfs_find_block_group(root, block_group, block_group = btrfs_find_block_group(root, block_group,
search_start, data, 0); search_start, data, 0);
cond_resched();
goto check_failed; goto check_failed;
error: error:
...@@ -1156,12 +1164,13 @@ printk("doing full scan!\n"); ...@@ -1156,12 +1164,13 @@ printk("doing full scan!\n");
*/ */
int btrfs_alloc_extent(struct btrfs_trans_handle *trans, int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 owner, struct btrfs_root *root, u64 owner,
u64 num_blocks, u64 search_start, u64 num_blocks, u64 hint_block,
u64 search_end, struct btrfs_key *ins, int data) u64 search_end, struct btrfs_key *ins, int data)
{ {
int ret; int ret;
int pending_ret; int pending_ret;
u64 super_blocks_used; u64 super_blocks_used;
u64 search_start = 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;
...@@ -1193,7 +1202,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, ...@@ -1193,7 +1202,7 @@ 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, &prealloc_key, 0); search_end, 0, &prealloc_key, 0);
if (ret) { if (ret) {
return ret; return ret;
} }
...@@ -1204,9 +1213,11 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, ...@@ -1204,9 +1213,11 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
search_start = info->extent_tree_prealloc[0] + 1; 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, ins, data); search_end, hint_block, ins, data);
if (ret) { if (ret) {
return ret; return ret;
} }
...@@ -1226,8 +1237,12 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, ...@@ -1226,8 +1237,12 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
else else
search_start = ins->objectid + ins->offset; 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, &prealloc_key, 0); search_end, hint_block,
&prealloc_key, 0);
if (ret) { if (ret) {
return ret; return ret;
} }
......
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