Commit 0579da42 authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse

Btrfs: Fixup last found extent caching

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 037e6390
CC=gcc CC=gcc
CFLAGS = -Wall CFLAGS = -g -Wall
headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h
objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o
......
...@@ -54,6 +54,7 @@ struct ctree_root { ...@@ -54,6 +54,7 @@ struct ctree_root {
struct tree_buffer *commit_root; struct tree_buffer *commit_root;
struct ctree_root *extent_root; struct ctree_root *extent_root;
struct key current_insert; struct key current_insert;
struct key last_insert;
int fp; int fp;
struct radix_tree_root cache_radix; struct radix_tree_root cache_radix;
struct radix_tree_root pinned_radix; struct radix_tree_root pinned_radix;
......
...@@ -186,6 +186,7 @@ static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root, ...@@ -186,6 +186,7 @@ static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root,
root->commit_root = NULL; root->commit_root = NULL;
root->node = read_tree_block(root, info->tree_root); root->node = read_tree_block(root, info->tree_root);
memset(&root->current_insert, 0, sizeof(root->current_insert)); memset(&root->current_insert, 0, sizeof(root->current_insert));
memset(&root->last_insert, 0, sizeof(root->last_insert));
return 0; return 0;
} }
......
...@@ -102,9 +102,12 @@ int btrfs_finish_extent_commit(struct ctree_root *root) ...@@ -102,9 +102,12 @@ int btrfs_finish_extent_commit(struct ctree_root *root)
ARRAY_SIZE(gang)); ARRAY_SIZE(gang));
if (!ret) if (!ret)
break; break;
for (i = 0; i < ret; i++) for (i = 0; i < ret; i++) {
radix_tree_delete(&extent_root->pinned_radix, gang[i]); radix_tree_delete(&extent_root->pinned_radix, gang[i]);
}
} }
extent_root->last_insert.objectid = 0;
extent_root->last_insert.offset = 0;
return 0; return 0;
} }
...@@ -170,6 +173,9 @@ int __free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks) ...@@ -170,6 +173,9 @@ int __free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks)
radix_tree_preload_end(); radix_tree_preload_end();
} }
ret = del_item(extent_root, &path); ret = del_item(extent_root, &path);
if (root != extent_root &&
extent_root->last_insert.objectid < blocknr)
extent_root->last_insert.objectid = blocknr;
if (ret) if (ret)
BUG(); BUG();
} }
...@@ -261,8 +267,11 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks, ...@@ -261,8 +267,11 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks,
int start_found; int start_found;
struct leaf *l; struct leaf *l;
struct ctree_root * root = orig_root->extent_root; struct ctree_root * root = orig_root->extent_root;
int total_needed = num_blocks + MAX_LEVEL * 3; int total_needed = num_blocks;
total_needed += (node_level(root->node->node.header.flags) + 1) * 3;
if (root->last_insert.objectid > search_start)
search_start = root->last_insert.objectid;
check_failed: check_failed:
init_path(&path); init_path(&path);
ins->objectid = search_start; ins->objectid = search_start;
...@@ -273,6 +282,9 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks, ...@@ -273,6 +282,9 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks,
if (ret < 0) if (ret < 0)
goto error; goto error;
if (path.slots[0] > 0)
path.slots[0]--;
while (1) { while (1) {
l = &path.nodes[0]->leaf; l = &path.nodes[0]->leaf;
slot = path.slots[0]; slot = path.slots[0];
...@@ -293,31 +305,21 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks, ...@@ -293,31 +305,21 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks,
ins->offset = (u64)-1; ins->offset = (u64)-1;
goto check_pending; goto check_pending;
} }
if (slot == 0) {
int last_slot = l->header.nritems - 1;
u64 span = l->items[last_slot].key.objectid;
span -= l->items[slot].key.objectid;
if (span + total_needed > last_slot - slot) {
path.slots[0] = last_slot + 1;
key = &l->items[last_slot].key;
last_block = key->objectid + key->offset;
start_found = 1;
continue;
}
}
key = &l->items[slot].key; key = &l->items[slot].key;
if (key->objectid >= search_start) { if (key->objectid >= search_start) {
if (start_found) { if (start_found) {
if (last_block < search_start)
last_block = search_start;
hole_size = key->objectid - last_block; hole_size = key->objectid - last_block;
if (hole_size > total_needed) { if (hole_size > total_needed) {
ins->objectid = last_block; ins->objectid = last_block;
ins->offset = hole_size; ins->offset = hole_size;
goto check_pending; goto check_pending;
} }
} else }
start_found = 1;
last_block = key->objectid + key->offset;
} }
start_found = 1;
last_block = key->objectid + key->offset;
path.slots[0]++; path.slots[0]++;
} }
// FIXME -ENOSPC // FIXME -ENOSPC
...@@ -335,9 +337,10 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks, ...@@ -335,9 +337,10 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks,
} }
} }
BUG_ON(root->current_insert.offset); BUG_ON(root->current_insert.offset);
root->current_insert.offset = total_needed; root->current_insert.offset = total_needed - num_blocks;
root->current_insert.objectid = ins->objectid + num_blocks; root->current_insert.objectid = ins->objectid + num_blocks;
root->current_insert.flags = 0; root->current_insert.flags = 0;
root->last_insert.objectid = ins->objectid;
ins->offset = num_blocks; ins->offset = num_blocks;
return 0; return 0;
error: error:
......
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