aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2013-03-01 17:45:50 -0500
committerAlasdair G Kergon <agk@redhat.com>2013-03-01 17:45:50 -0500
commit4e7f1f9089660aec3b5ab2645ce62777c6f4c6a2 (patch)
tree56f012273947dcd88e4a73944aae37d01f023b56 /drivers/md
parentb0d8ed4d96a26ef3ac54a4aa8911c9413070662e (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')
-rw-r--r--drivers/md/persistent-data/dm-btree-internal.h1
-rw-r--r--drivers/md/persistent-data/dm-btree-spine.c7
-rw-r--r--drivers/md/persistent-data/dm-btree.c52
-rw-r--r--drivers/md/persistent-data/dm-btree.h9
4 files changed, 69 insertions, 0 deletions
diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h
index accbb05f17b6..37d367bb9aa8 100644
--- a/drivers/md/persistent-data/dm-btree-internal.h
+++ b/drivers/md/persistent-data/dm-btree-internal.h
@@ -64,6 +64,7 @@ struct ro_spine {
64void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info); 64void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info);
65int exit_ro_spine(struct ro_spine *s); 65int exit_ro_spine(struct ro_spine *s);
66int ro_step(struct ro_spine *s, dm_block_t new_child); 66int ro_step(struct ro_spine *s, dm_block_t new_child);
67void ro_pop(struct ro_spine *s);
67struct btree_node *ro_node(struct ro_spine *s); 68struct btree_node *ro_node(struct ro_spine *s);
68 69
69struct shadow_spine { 70struct shadow_spine {
diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c
index f199a0c4ed04..cf9fd676ae44 100644
--- a/drivers/md/persistent-data/dm-btree-spine.c
+++ b/drivers/md/persistent-data/dm-btree-spine.c
@@ -164,6 +164,13 @@ int ro_step(struct ro_spine *s, dm_block_t new_child)
164 return r; 164 return r;
165} 165}
166 166
167void ro_pop(struct ro_spine *s)
168{
169 BUG_ON(!s->count);
170 --s->count;
171 unlock_block(s->info, s->nodes[s->count]);
172}
173
167struct btree_node *ro_node(struct ro_spine *s) 174struct btree_node *ro_node(struct ro_spine *s)
168{ 175{
169 struct dm_block *block; 176 struct dm_block *block;
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}
809EXPORT_SYMBOL_GPL(dm_btree_find_highest_key); 809EXPORT_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 */
815static 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
841out:
842 ro_pop(s);
843 return r;
844}
845
846int 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}
861EXPORT_SYMBOL_GPL(dm_btree_walk);
diff --git a/drivers/md/persistent-data/dm-btree.h b/drivers/md/persistent-data/dm-btree.h
index fced8316bca2..8672d159e0b5 100644
--- a/drivers/md/persistent-data/dm-btree.h
+++ b/drivers/md/persistent-data/dm-btree.h
@@ -142,4 +142,13 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
142int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root, 142int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root,
143 uint64_t *result_keys); 143 uint64_t *result_keys);
144 144
145/*
146 * Iterate through the a btree, calling fn() on each entry.
147 * It only works for single level trees and is internally recursive, so
148 * monitor stack usage carefully.
149 */
150int dm_btree_walk(struct dm_btree_info *info, dm_block_t root,
151 int (*fn)(void *context, uint64_t *keys, void *leaf),
152 void *context);
153
145#endif /* _LINUX_DM_BTREE_H */ 154#endif /* _LINUX_DM_BTREE_H */