···994994 return walk_node(info, root, fn, context);995995}996996EXPORT_SYMBOL_GPL(dm_btree_walk);997997+998998+/*----------------------------------------------------------------*/999999+10001000+static void prefetch_values(struct dm_btree_cursor *c)10011001+{10021002+ unsigned i, nr;10031003+ __le64 value_le;10041004+ struct cursor_node *n = c->nodes + c->depth - 1;10051005+ struct btree_node *bn = dm_block_data(n->b);10061006+ struct dm_block_manager *bm = dm_tm_get_bm(c->info->tm);10071007+10081008+ BUG_ON(c->info->value_type.size != sizeof(value_le));10091009+10101010+ nr = le32_to_cpu(bn->header.nr_entries);10111011+ for (i = 0; i < nr; i++) {10121012+ memcpy(&value_le, value_ptr(bn, i), sizeof(value_le));10131013+ dm_bm_prefetch(bm, le64_to_cpu(value_le));10141014+ }10151015+}10161016+10171017+static bool leaf_node(struct dm_btree_cursor *c)10181018+{10191019+ struct cursor_node *n = c->nodes + c->depth - 1;10201020+ struct btree_node *bn = dm_block_data(n->b);10211021+10221022+ return le32_to_cpu(bn->header.flags) & LEAF_NODE;10231023+}10241024+10251025+static int push_node(struct dm_btree_cursor *c, dm_block_t b)10261026+{10271027+ int r;10281028+ struct cursor_node *n = c->nodes + c->depth;10291029+10301030+ if (c->depth >= DM_BTREE_CURSOR_MAX_DEPTH - 1) {10311031+ DMERR("couldn't push cursor node, stack depth too high");10321032+ return -EINVAL;10331033+ }10341034+10351035+ r = bn_read_lock(c->info, b, &n->b);10361036+ if (r)10371037+ return r;10381038+10391039+ n->index = 0;10401040+ c->depth++;10411041+10421042+ if (c->prefetch_leaves || !leaf_node(c))10431043+ prefetch_values(c);10441044+10451045+ return 0;10461046+}10471047+10481048+static void pop_node(struct dm_btree_cursor *c)10491049+{10501050+ c->depth--;10511051+ unlock_block(c->info, c->nodes[c->depth].b);10521052+}10531053+10541054+static int inc_or_backtrack(struct dm_btree_cursor *c)10551055+{10561056+ struct cursor_node *n;10571057+ struct btree_node *bn;10581058+10591059+ for (;;) {10601060+ if (!c->depth)10611061+ return -ENODATA;10621062+10631063+ n = c->nodes + c->depth - 1;10641064+ bn = dm_block_data(n->b);10651065+10661066+ n->index++;10671067+ if (n->index < le32_to_cpu(bn->header.nr_entries))10681068+ break;10691069+10701070+ pop_node(c);10711071+ }10721072+10731073+ return 0;10741074+}10751075+10761076+static int find_leaf(struct dm_btree_cursor *c)10771077+{10781078+ int r = 0;10791079+ struct cursor_node *n;10801080+ struct btree_node *bn;10811081+ __le64 value_le;10821082+10831083+ for (;;) {10841084+ n = c->nodes + c->depth - 1;10851085+ bn = dm_block_data(n->b);10861086+10871087+ if (le32_to_cpu(bn->header.flags) & LEAF_NODE)10881088+ break;10891089+10901090+ memcpy(&value_le, value_ptr(bn, n->index), sizeof(value_le));10911091+ r = push_node(c, le64_to_cpu(value_le));10921092+ if (r) {10931093+ DMERR("push_node failed");10941094+ break;10951095+ }10961096+ }10971097+10981098+ if (!r && (le32_to_cpu(bn->header.nr_entries) == 0))10991099+ return -ENODATA;11001100+11011101+ return r;11021102+}11031103+11041104+int dm_btree_cursor_begin(struct dm_btree_info *info, dm_block_t root,11051105+ bool prefetch_leaves, struct dm_btree_cursor *c)11061106+{11071107+ int r;11081108+11091109+ c->info = info;11101110+ c->root = root;11111111+ c->depth = 0;11121112+ c->prefetch_leaves = prefetch_leaves;11131113+11141114+ r = push_node(c, root);11151115+ if (r)11161116+ return r;11171117+11181118+ return find_leaf(c);11191119+}11201120+EXPORT_SYMBOL_GPL(dm_btree_cursor_begin);11211121+11221122+void dm_btree_cursor_end(struct dm_btree_cursor *c)11231123+{11241124+ while (c->depth)11251125+ pop_node(c);11261126+}11271127+EXPORT_SYMBOL_GPL(dm_btree_cursor_end);11281128+11291129+int dm_btree_cursor_next(struct dm_btree_cursor *c)11301130+{11311131+ int r = inc_or_backtrack(c);11321132+ if (!r) {11331133+ r = find_leaf(c);11341134+ if (r)11351135+ DMERR("find_leaf failed");11361136+ }11371137+11381138+ return r;11391139+}11401140+EXPORT_SYMBOL_GPL(dm_btree_cursor_next);11411141+11421142+int dm_btree_cursor_get_value(struct dm_btree_cursor *c, uint64_t *key, void *value_le)11431143+{11441144+ if (c->depth) {11451145+ struct cursor_node *n = c->nodes + c->depth - 1;11461146+ struct btree_node *bn = dm_block_data(n->b);11471147+11481148+ if (le32_to_cpu(bn->header.flags) & INTERNAL_NODE)11491149+ return -EINVAL;11501150+11511151+ *key = le64_to_cpu(*key_ptr(bn, n->index));11521152+ memcpy(value_le, value_ptr(bn, n->index), c->info->value_type.size);11531153+ return 0;11541154+11551155+ } else11561156+ return -ENODATA;11571157+}11581158+EXPORT_SYMBOL_GPL(dm_btree_cursor_get_value);
+35
drivers/md/persistent-data/dm-btree.h
···176176 int (*fn)(void *context, uint64_t *keys, void *leaf),177177 void *context);178178179179+180180+/*----------------------------------------------------------------*/181181+182182+/*183183+ * Cursor API. This does not follow the rolling lock convention. Since we184184+ * know the order that values are required we can issue prefetches to speed185185+ * up iteration. Use on a single level btree only.186186+ */187187+#define DM_BTREE_CURSOR_MAX_DEPTH 16188188+189189+struct cursor_node {190190+ struct dm_block *b;191191+ unsigned index;192192+};193193+194194+struct dm_btree_cursor {195195+ struct dm_btree_info *info;196196+ dm_block_t root;197197+198198+ bool prefetch_leaves;199199+ unsigned depth;200200+ struct cursor_node nodes[DM_BTREE_CURSOR_MAX_DEPTH];201201+};202202+203203+/*204204+ * Creates a fresh cursor. If prefetch_leaves is set then it is assumed205205+ * the btree contains block indexes that will be prefetched. The cursor is206206+ * quite large, so you probably don't want to put it on the stack.207207+ */208208+int dm_btree_cursor_begin(struct dm_btree_info *info, dm_block_t root,209209+ bool prefetch_leaves, struct dm_btree_cursor *c);210210+void dm_btree_cursor_end(struct dm_btree_cursor *c);211211+int dm_btree_cursor_next(struct dm_btree_cursor *c);212212+int dm_btree_cursor_get_value(struct dm_btree_cursor *c, uint64_t *key, void *value_le);213213+179214#endif /* _LINUX_DM_BTREE_H */