diff options
author | Joe Thornber <ejt@redhat.com> | 2013-03-01 17:45:50 -0500 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2013-03-01 17:45:50 -0500 |
commit | 4e7f1f9089660aec3b5ab2645ce62777c6f4c6a2 (patch) | |
tree | 56f012273947dcd88e4a73944aae37d01f023b56 /drivers/md/persistent-data/dm-btree.c | |
parent | b0d8ed4d96a26ef3ac54a4aa8911c9413070662e (diff) |
dm persistent data: add btree_walk
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>
Diffstat (limited to 'drivers/md/persistent-data/dm-btree.c')
-rw-r--r-- | drivers/md/persistent-data/dm-btree.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c index 4caf66918cdb..35865425e4b4 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c | |||
@@ -807,3 +807,55 @@ int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root, | |||
807 | return r ? r : count; | 807 | return r ? r : count; |
808 | } | 808 | } |
809 | EXPORT_SYMBOL_GPL(dm_btree_find_highest_key); | 809 | EXPORT_SYMBOL_GPL(dm_btree_find_highest_key); |
810 | |||
811 | /* | ||
812 | * FIXME: We shouldn't use a recursive algorithm when we have limited stack | ||
813 | * space. Also this only works for single level trees. | ||
814 | */ | ||
815 | static int walk_node(struct ro_spine *s, dm_block_t block, | ||
816 | int (*fn)(void *context, uint64_t *keys, void *leaf), | ||
817 | void *context) | ||
818 | { | ||
819 | int r; | ||
820 | unsigned i, nr; | ||
821 | struct btree_node *n; | ||
822 | uint64_t keys; | ||
823 | |||
824 | r = ro_step(s, block); | ||
825 | n = ro_node(s); | ||
826 | |||
827 | nr = le32_to_cpu(n->header.nr_entries); | ||
828 | for (i = 0; i < nr; i++) { | ||
829 | if (le32_to_cpu(n->header.flags) & INTERNAL_NODE) { | ||
830 | r = walk_node(s, value64(n, i), fn, context); | ||
831 | if (r) | ||
832 | goto out; | ||
833 | } else { | ||
834 | keys = le64_to_cpu(*key_ptr(n, i)); | ||
835 | r = fn(context, &keys, value_ptr(n, i)); | ||
836 | if (r) | ||
837 | goto out; | ||
838 | } | ||
839 | } | ||
840 | |||
841 | out: | ||
842 | ro_pop(s); | ||
843 | return r; | ||
844 | } | ||
845 | |||
846 | int dm_btree_walk(struct dm_btree_info *info, dm_block_t root, | ||
847 | int (*fn)(void *context, uint64_t *keys, void *leaf), | ||
848 | void *context) | ||
849 | { | ||
850 | int r; | ||
851 | struct ro_spine spine; | ||
852 | |||
853 | BUG_ON(info->levels > 1); | ||
854 | |||
855 | init_ro_spine(&spine, info); | ||
856 | r = walk_node(&spine, root, fn, context); | ||
857 | exit_ro_spine(&spine); | ||
858 | |||
859 | return r; | ||
860 | } | ||
861 | EXPORT_SYMBOL_GPL(dm_btree_walk); | ||