Skip to content

Commit fdd1315

Browse files
jthornbersnitm
authored andcommitted
dm array: introduce cursor api
More efficient way to iterate an array due to prefetching (makes use of the new dm_btree_cursor_* api). Signed-off-by: Joe Thornber <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent 7d111c8 commit fdd1315

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

drivers/md/persistent-data/dm-array.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,3 +899,89 @@ int dm_array_walk(struct dm_array_info *info, dm_block_t root,
899899
EXPORT_SYMBOL_GPL(dm_array_walk);
900900

901901
/*----------------------------------------------------------------*/
902+
903+
static int load_ablock(struct dm_array_cursor *c)
904+
{
905+
int r;
906+
__le64 value_le;
907+
uint64_t key;
908+
909+
if (c->block)
910+
unlock_ablock(c->info, c->block);
911+
912+
c->block = NULL;
913+
c->ab = NULL;
914+
c->index = 0;
915+
916+
r = dm_btree_cursor_get_value(&c->cursor, &key, &value_le);
917+
if (r) {
918+
DMERR("dm_btree_cursor_get_value failed");
919+
dm_btree_cursor_end(&c->cursor);
920+
921+
} else {
922+
r = get_ablock(c->info, le64_to_cpu(value_le), &c->block, &c->ab);
923+
if (r) {
924+
DMERR("get_ablock failed");
925+
dm_btree_cursor_end(&c->cursor);
926+
}
927+
}
928+
929+
return r;
930+
}
931+
932+
int dm_array_cursor_begin(struct dm_array_info *info, dm_block_t root,
933+
struct dm_array_cursor *c)
934+
{
935+
int r;
936+
937+
memset(c, 0, sizeof(*c));
938+
c->info = info;
939+
r = dm_btree_cursor_begin(&info->btree_info, root, true, &c->cursor);
940+
if (r) {
941+
DMERR("couldn't create btree cursor");
942+
return r;
943+
}
944+
945+
return load_ablock(c);
946+
}
947+
EXPORT_SYMBOL_GPL(dm_array_cursor_begin);
948+
949+
void dm_array_cursor_end(struct dm_array_cursor *c)
950+
{
951+
if (c->block) {
952+
unlock_ablock(c->info, c->block);
953+
dm_btree_cursor_end(&c->cursor);
954+
}
955+
}
956+
EXPORT_SYMBOL_GPL(dm_array_cursor_end);
957+
958+
int dm_array_cursor_next(struct dm_array_cursor *c)
959+
{
960+
int r;
961+
962+
if (!c->block)
963+
return -ENODATA;
964+
965+
c->index++;
966+
967+
if (c->index >= le32_to_cpu(c->ab->nr_entries)) {
968+
r = dm_btree_cursor_next(&c->cursor);
969+
if (r)
970+
return r;
971+
972+
r = load_ablock(c);
973+
if (r)
974+
return r;
975+
}
976+
977+
return 0;
978+
}
979+
EXPORT_SYMBOL_GPL(dm_array_cursor_next);
980+
981+
void dm_array_cursor_get_value(struct dm_array_cursor *c, void **value_le)
982+
{
983+
*value_le = element_at(c->info, c->ab, c->index);
984+
}
985+
EXPORT_SYMBOL_GPL(dm_array_cursor_get_value);
986+
987+
/*----------------------------------------------------------------*/

drivers/md/persistent-data/dm-array.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,4 +182,37 @@ int dm_array_walk(struct dm_array_info *info, dm_block_t root,
182182

183183
/*----------------------------------------------------------------*/
184184

185+
/*
186+
* Cursor api.
187+
*
188+
* This lets you iterate through all the entries in an array efficiently
189+
* (it will preload metadata).
190+
*
191+
* I'm using a cursor, rather than a walk function with a callback because
192+
* the cache target needs to iterate both the mapping and hint arrays in
193+
* unison.
194+
*/
195+
struct dm_array_cursor {
196+
struct dm_array_info *info;
197+
struct dm_btree_cursor cursor;
198+
199+
struct dm_block *block;
200+
struct array_block *ab;
201+
unsigned index;
202+
};
203+
204+
int dm_array_cursor_begin(struct dm_array_info *info,
205+
dm_block_t root, struct dm_array_cursor *c);
206+
void dm_array_cursor_end(struct dm_array_cursor *c);
207+
208+
uint32_t dm_array_cursor_index(struct dm_array_cursor *c);
209+
int dm_array_cursor_next(struct dm_array_cursor *c);
210+
211+
/*
212+
* value_le is only valid while the cursor points at the current value.
213+
*/
214+
void dm_array_cursor_get_value(struct dm_array_cursor *c, void **value_le);
215+
216+
/*----------------------------------------------------------------*/
217+
185218
#endif /* _LINUX_DM_ARRAY_H */

0 commit comments

Comments
 (0)