summaryrefslogtreecommitdiff
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-08-10 14:42:37 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-08-10 14:42:37 -0400
commitf2183bde1a918d338337955c8e8ba29bd8f5e7b1 (patch)
treee27baea3779112618d2158902270c460444feeff /fs/btrfs/ctree.c
parente9d0b13b5bbb58c9b840e407a8d181442f799966 (diff)
downloadlwn-f2183bde1a918d338337955c8e8ba29bd8f5e7b1.tar.gz
lwn-f2183bde1a918d338337955c8e8ba29bd8f5e7b1.zip
Btrfs: Add BH_Defrag to mark buffers that are in need of defragging
This allows the tree walking code to defrag only the newly allocated buffers, it seems to be a good balance between perfect defragging and the performance hit of repeatedly reallocating blocks. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index ee1ae00d2827..7cf43da5e78e 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -175,6 +175,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
int end_slot;
int i;
int err = 0;
+ int parent_level;
if (trans->transaction != root->fs_info->running_transaction) {
printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid,
@@ -188,6 +189,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
}
parent_node = btrfs_buffer_node(parent);
parent_nritems = btrfs_header_nritems(&parent_node->header);
+ parent_level = btrfs_header_level(&parent_node->header);
start_slot = 0;
end_slot = parent_nritems;
@@ -215,13 +217,16 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
cur_bh = btrfs_find_tree_block(root, blocknr);
if (!cur_bh || !buffer_uptodate(cur_bh) ||
- buffer_locked(cur_bh)) {
+ buffer_locked(cur_bh) || !buffer_defrag(cur_bh)) {
if (cache_only) {
brelse(cur_bh);
continue;
}
- brelse(cur_bh);
- cur_bh = read_tree_block(root, blocknr);
+ if (!cur_bh || !buffer_uptodate(cur_bh) ||
+ buffer_locked(cur_bh)) {
+ brelse(cur_bh);
+ cur_bh = read_tree_block(root, blocknr);
+ }
}
if (search_start == 0)
search_start = last_block & ~((u64)65535);
@@ -232,6 +237,9 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
if (err)
break;
search_start = bh_blocknr(tmp_bh);
+ *last_ret = search_start;
+ if (parent_level == 1)
+ clear_buffer_defrag(tmp_bh);
brelse(tmp_bh);
}
return err;
@@ -811,16 +819,10 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
clear_radix_bit(&found, blocknr);
if (nread > 32)
continue;
- if (direction > 0 && cluster_start <= blocknr &&
- cluster_start + 8 > blocknr) {
- cluster_start = blocknr;
+ if (close_blocks(cluster_start, blocknr)) {
readahead_tree_block(root, blocknr);
nread++;
- } else if (direction < 0 && cluster_start >= blocknr &&
- blocknr + 8 > cluster_start) {
cluster_start = blocknr;
- readahead_tree_block(root, blocknr);
- nread++;
}
}
}