Skip to content

Commit

Permalink
Btrfs: recursion free-first pass
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Chris Mason authored and David Woodhouse committed Mar 10, 2007
1 parent 0579da4 commit 20524f0
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 3 deletions.
98 changes: 96 additions & 2 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static int inc_block_ref(struct ctree_root *root, u64 blocknr)
return 0;
}

static int lookup_block_ref(struct ctree_root *root, u64 blocknr, int *refs)
static int lookup_block_ref(struct ctree_root *root, u64 blocknr, u32 *refs)
{
struct ctree_path path;
int ret;
Expand Down Expand Up @@ -415,6 +415,100 @@ struct tree_buffer *alloc_free_block(struct ctree_root *root)
return buf;
}

int walk_down_tree(struct ctree_root *root, struct ctree_path *path, int *level)
{
struct tree_buffer *next;
struct tree_buffer *cur;
u64 blocknr;
int ret;
u32 refs;

ret = lookup_block_ref(root, path->nodes[*level]->blocknr, &refs);
BUG_ON(ret);
if (refs > 1)
goto out;
while(*level > 0) {
cur = path->nodes[*level];
if (path->slots[*level] >= cur->node.header.nritems)
break;
blocknr = cur->node.blockptrs[path->slots[*level]];
ret = lookup_block_ref(root, blocknr, &refs);
if (refs != 1 || *level == 1) {
path->slots[*level]++;
ret = free_extent(root, blocknr, 1);
BUG_ON(ret);
continue;
}
BUG_ON(ret);
next = read_tree_block(root, blocknr);
if (path->nodes[*level-1]) {
tree_block_release(root, path->nodes[*level-1]);
}
path->nodes[*level-1] = next;
*level = node_level(next->node.header.flags);
path->slots[*level] = 0;
}
out:
ret = free_extent(root, path->nodes[*level]->blocknr, 1);
path->nodes[*level] = NULL;
*level += 1;
BUG_ON(ret);
return 0;
}

int walk_up_tree(struct ctree_root *root, struct ctree_path *path, int *level)
{
int i;
int slot;
int ret;
for(i = *level; i < MAX_LEVEL - 1 && path->nodes[i]; i++) {
slot = path->slots[i];
if (slot < path->nodes[i]->node.header.nritems - 1) {
path->slots[i]++;
*level = i;
return 0;
} else {
ret = free_extent(root,
path->nodes[*level]->blocknr, 1);
*level = i + 1;
BUG_ON(ret);
}
}
return 1;
}

int btrfs_drop_snapshot(struct ctree_root *root, struct tree_buffer *snap)
{
int ret;
int level;
struct ctree_path path;
int i;
int orig_level;

init_path(&path);

level = node_level(snap->node.header.flags);
orig_level = level;
path.nodes[level] = snap;
path.slots[level] = 0;
while(1) {
ret = walk_down_tree(root, &path, &level);
if (ret > 0)
break;
ret = walk_up_tree(root, &path, &level);
if (ret > 0)
break;
}
for (i = 0; i < orig_level; i++) {
if (path.nodes[i])
tree_block_release(root, path.nodes[i]);
}

return 0;
}


#if 0
int btrfs_drop_snapshot(struct ctree_root *root, struct tree_buffer *snap)
{
int ret;
Expand All @@ -441,4 +535,4 @@ int btrfs_drop_snapshot(struct ctree_root *root, struct tree_buffer *snap)
BUG_ON(ret);
return 0;
}

#endif
5 changes: 4 additions & 1 deletion fs/btrfs/quick-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
/* for testing only */
int next_key(int i, int max_key) {
return rand() % max_key;
//return i;
// return i;
}

int main(int ac, char **av) {
Expand Down Expand Up @@ -44,6 +44,9 @@ int main(int ac, char **av) {
if (!ret)
tree_size++;
free(buf);
if (i == run_size - 5) {
commit_transaction(root, &super);
}

}
close_ctree(root, &super);
Expand Down

0 comments on commit 20524f0

Please sign in to comment.