Skip to content

Commit

Permalink
dm persistent data: add btree_walk
Browse files Browse the repository at this point in the history
Add dm_btree_walk to iterate through the contents of a btree.
This will be used by the dm cache target.

Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
  • Loading branch information
Joe Thornber authored and Alasdair G Kergon committed Mar 1, 2013
1 parent b0d8ed4 commit 4e7f1f9
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/md/persistent-data/dm-btree-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ struct ro_spine {
void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info);
int exit_ro_spine(struct ro_spine *s);
int ro_step(struct ro_spine *s, dm_block_t new_child);
void ro_pop(struct ro_spine *s);
struct btree_node *ro_node(struct ro_spine *s);

struct shadow_spine {
Expand Down
7 changes: 7 additions & 0 deletions drivers/md/persistent-data/dm-btree-spine.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,13 @@ int ro_step(struct ro_spine *s, dm_block_t new_child)
return r;
}

void ro_pop(struct ro_spine *s)
{
BUG_ON(!s->count);
--s->count;
unlock_block(s->info, s->nodes[s->count]);
}

struct btree_node *ro_node(struct ro_spine *s)
{
struct dm_block *block;
Expand Down
52 changes: 52 additions & 0 deletions drivers/md/persistent-data/dm-btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,55 @@ int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root,
return r ? r : count;
}
EXPORT_SYMBOL_GPL(dm_btree_find_highest_key);

/*
* FIXME: We shouldn't use a recursive algorithm when we have limited stack
* space. Also this only works for single level trees.
*/
static int walk_node(struct ro_spine *s, dm_block_t block,
int (*fn)(void *context, uint64_t *keys, void *leaf),
void *context)
{
int r;
unsigned i, nr;
struct btree_node *n;
uint64_t keys;

r = ro_step(s, block);
n = ro_node(s);

nr = le32_to_cpu(n->header.nr_entries);
for (i = 0; i < nr; i++) {
if (le32_to_cpu(n->header.flags) & INTERNAL_NODE) {
r = walk_node(s, value64(n, i), fn, context);
if (r)
goto out;
} else {
keys = le64_to_cpu(*key_ptr(n, i));
r = fn(context, &keys, value_ptr(n, i));
if (r)
goto out;
}
}

out:
ro_pop(s);
return r;
}

int dm_btree_walk(struct dm_btree_info *info, dm_block_t root,
int (*fn)(void *context, uint64_t *keys, void *leaf),
void *context)
{
int r;
struct ro_spine spine;

BUG_ON(info->levels > 1);

init_ro_spine(&spine, info);
r = walk_node(&spine, root, fn, context);
exit_ro_spine(&spine);

return r;
}
EXPORT_SYMBOL_GPL(dm_btree_walk);
9 changes: 9 additions & 0 deletions drivers/md/persistent-data/dm-btree.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,13 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root,
uint64_t *result_keys);

/*
* Iterate through the a btree, calling fn() on each entry.
* It only works for single level trees and is internally recursive, so
* monitor stack usage carefully.
*/
int dm_btree_walk(struct dm_btree_info *info, dm_block_t root,
int (*fn)(void *context, uint64_t *keys, void *leaf),
void *context);

#endif /* _LINUX_DM_BTREE_H */

0 comments on commit 4e7f1f9

Please sign in to comment.