aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-06-25 16:01:31 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:03 -0400
commite7a84565bcdb239caad29ccbe559ef978090ac7e (patch)
treeaaeba005e713cde2030c27451d98847accff116d /fs/btrfs/ctree.c
parenta74a4b97b61beede185b4b3ad359d7d378b0d312 (diff)
Btrfs: Add btree locking to the tree defragmentation code
The online btree defragger is simplified and rewritten to use standard btree searches instead of a walk up / down mechanism. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c46
1 files changed, 37 insertions, 9 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 40f0e0cb804b..7f4cc2b88d09 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -354,7 +354,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
354 struct btrfs_key *progress) 354 struct btrfs_key *progress)
355{ 355{
356 struct extent_buffer *cur; 356 struct extent_buffer *cur;
357 struct extent_buffer *tmp;
358 u64 blocknr; 357 u64 blocknr;
359 u64 gen; 358 u64 gen;
360 u64 search_start = *last_ret; 359 u64 search_start = *last_ret;
@@ -370,9 +369,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
370 int progress_passed = 0; 369 int progress_passed = 0;
371 struct btrfs_disk_key disk_key; 370 struct btrfs_disk_key disk_key;
372 371
373 /* FIXME this code needs locking */
374 return 0;
375
376 parent_level = btrfs_header_level(parent); 372 parent_level = btrfs_header_level(parent);
377 if (cache_only && parent_level != 1) 373 if (cache_only && parent_level != 1)
378 return 0; 374 return 0;
@@ -454,20 +450,23 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
454 if (search_start == 0) 450 if (search_start == 0)
455 search_start = last_block; 451 search_start = last_block;
456 452
453 btrfs_tree_lock(cur);
457 err = __btrfs_cow_block(trans, root, cur, parent, i, 454 err = __btrfs_cow_block(trans, root, cur, parent, i,
458 &tmp, search_start, 455 &cur, search_start,
459 min(16 * blocksize, 456 min(16 * blocksize,
460 (end_slot - i) * blocksize)); 457 (end_slot - i) * blocksize));
461 if (err) { 458 if (err) {
459 btrfs_tree_unlock(cur);
462 free_extent_buffer(cur); 460 free_extent_buffer(cur);
463 break; 461 break;
464 } 462 }
465 search_start = tmp->start; 463 search_start = cur->start;
466 last_block = tmp->start; 464 last_block = cur->start;
467 *last_ret = search_start; 465 *last_ret = search_start;
468 if (parent_level == 1) 466 if (parent_level == 1)
469 btrfs_clear_buffer_defrag(tmp); 467 btrfs_clear_buffer_defrag(cur);
470 free_extent_buffer(tmp); 468 btrfs_tree_unlock(cur);
469 free_extent_buffer(cur);
471 } 470 }
472 if (parent->map_token) { 471 if (parent->map_token) {
473 unmap_extent_buffer(parent, parent->map_token, 472 unmap_extent_buffer(parent, parent->map_token,
@@ -2970,6 +2969,35 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path)
2970 return 1; 2969 return 1;
2971} 2970}
2972 2971
2972int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path,
2973 struct btrfs_key *key, int lowest_level)
2974{
2975 int level = lowest_level;
2976 int slot;
2977 struct extent_buffer *c;
2978
2979 while(level < BTRFS_MAX_LEVEL) {
2980 if (!path->nodes[level])
2981 return 1;
2982
2983 slot = path->slots[level] + 1;
2984 c = path->nodes[level];
2985 if (slot >= btrfs_header_nritems(c)) {
2986 level++;
2987 if (level == BTRFS_MAX_LEVEL) {
2988 return 1;
2989 }
2990 continue;
2991 }
2992 if (level == 0)
2993 btrfs_item_key_to_cpu(c, key, slot);
2994 else
2995 btrfs_node_key_to_cpu(c, key, slot);
2996 return 0;
2997 }
2998 return 1;
2999}
3000
2973/* 3001/*
2974 * search the tree again to find a leaf with greater keys 3002 * search the tree again to find a leaf with greater keys
2975 * returns 0 if it found something or 1 if there are no greater leaves. 3003 * returns 0 if it found something or 1 if there are no greater leaves.