aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-03-10 06:35:47 -0500
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-03-10 06:35:47 -0500
commit20524f02260910db1e67bd5335d3854e5e555efc (patch)
tree3fd221fbd79201e5d49ca23bc262c54dad5899f4
parent0579da4280812f34f382fb0f8004d7b0219e7a33 (diff)
Btrfs: recursion free-first pass
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/extent-tree.c98
-rw-r--r--fs/btrfs/quick-test.c5
2 files changed, 100 insertions, 3 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index dd11532cb2f6..6fbaece43ff6 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -50,7 +50,7 @@ static int inc_block_ref(struct ctree_root *root, u64 blocknr)
50 return 0; 50 return 0;
51} 51}
52 52
53static int lookup_block_ref(struct ctree_root *root, u64 blocknr, int *refs) 53static int lookup_block_ref(struct ctree_root *root, u64 blocknr, u32 *refs)
54{ 54{
55 struct ctree_path path; 55 struct ctree_path path;
56 int ret; 56 int ret;
@@ -415,6 +415,100 @@ struct tree_buffer *alloc_free_block(struct ctree_root *root)
415 return buf; 415 return buf;
416} 416}
417 417
418int walk_down_tree(struct ctree_root *root, struct ctree_path *path, int *level)
419{
420 struct tree_buffer *next;
421 struct tree_buffer *cur;
422 u64 blocknr;
423 int ret;
424 u32 refs;
425
426 ret = lookup_block_ref(root, path->nodes[*level]->blocknr, &refs);
427 BUG_ON(ret);
428 if (refs > 1)
429 goto out;
430 while(*level > 0) {
431 cur = path->nodes[*level];
432 if (path->slots[*level] >= cur->node.header.nritems)
433 break;
434 blocknr = cur->node.blockptrs[path->slots[*level]];
435 ret = lookup_block_ref(root, blocknr, &refs);
436 if (refs != 1 || *level == 1) {
437 path->slots[*level]++;
438 ret = free_extent(root, blocknr, 1);
439 BUG_ON(ret);
440 continue;
441 }
442 BUG_ON(ret);
443 next = read_tree_block(root, blocknr);
444 if (path->nodes[*level-1]) {
445 tree_block_release(root, path->nodes[*level-1]);
446 }
447 path->nodes[*level-1] = next;
448 *level = node_level(next->node.header.flags);
449 path->slots[*level] = 0;
450 }
451out:
452 ret = free_extent(root, path->nodes[*level]->blocknr, 1);
453 path->nodes[*level] = NULL;
454 *level += 1;
455 BUG_ON(ret);
456 return 0;
457}
458
459int walk_up_tree(struct ctree_root *root, struct ctree_path *path, int *level)
460{
461 int i;
462 int slot;
463 int ret;
464 for(i = *level; i < MAX_LEVEL - 1 && path->nodes[i]; i++) {
465 slot = path->slots[i];
466 if (slot < path->nodes[i]->node.header.nritems - 1) {
467 path->slots[i]++;
468 *level = i;
469 return 0;
470 } else {
471 ret = free_extent(root,
472 path->nodes[*level]->blocknr, 1);
473 *level = i + 1;
474 BUG_ON(ret);
475 }
476 }
477 return 1;
478}
479
480int btrfs_drop_snapshot(struct ctree_root *root, struct tree_buffer *snap)
481{
482 int ret;
483 int level;
484 struct ctree_path path;
485 int i;
486 int orig_level;
487
488 init_path(&path);
489
490 level = node_level(snap->node.header.flags);
491 orig_level = level;
492 path.nodes[level] = snap;
493 path.slots[level] = 0;
494 while(1) {
495 ret = walk_down_tree(root, &path, &level);
496 if (ret > 0)
497 break;
498 ret = walk_up_tree(root, &path, &level);
499 if (ret > 0)
500 break;
501 }
502 for (i = 0; i < orig_level; i++) {
503 if (path.nodes[i])
504 tree_block_release(root, path.nodes[i]);
505 }
506
507 return 0;
508}
509
510
511#if 0
418int btrfs_drop_snapshot(struct ctree_root *root, struct tree_buffer *snap) 512int btrfs_drop_snapshot(struct ctree_root *root, struct tree_buffer *snap)
419{ 513{
420 int ret; 514 int ret;
@@ -441,4 +535,4 @@ int btrfs_drop_snapshot(struct ctree_root *root, struct tree_buffer *snap)
441 BUG_ON(ret); 535 BUG_ON(ret);
442 return 0; 536 return 0;
443} 537}
444 538#endif
diff --git a/fs/btrfs/quick-test.c b/fs/btrfs/quick-test.c
index 6400c7100a6a..ccca9b2c14a3 100644
--- a/fs/btrfs/quick-test.c
+++ b/fs/btrfs/quick-test.c
@@ -9,7 +9,7 @@
9/* for testing only */ 9/* for testing only */
10int next_key(int i, int max_key) { 10int next_key(int i, int max_key) {
11 return rand() % max_key; 11 return rand() % max_key;
12 //return i; 12 // return i;
13} 13}
14 14
15int main(int ac, char **av) { 15int main(int ac, char **av) {
@@ -44,6 +44,9 @@ int main(int ac, char **av) {
44 if (!ret) 44 if (!ret)
45 tree_size++; 45 tree_size++;
46 free(buf); 46 free(buf);
47 if (i == run_size - 5) {
48 commit_transaction(root, &super);
49 }
47 50
48 } 51 }
49 close_ctree(root, &super); 52 close_ctree(root, &super);