summaryrefslogtreecommitdiff
path: root/libbcachefs/btree_iter.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/btree_iter.c')
-rw-r--r--libbcachefs/btree_iter.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/libbcachefs/btree_iter.c b/libbcachefs/btree_iter.c
index ecad24fa..46df99fe 100644
--- a/libbcachefs/btree_iter.c
+++ b/libbcachefs/btree_iter.c
@@ -252,6 +252,8 @@ static int __bch2_btree_iter_unlock(struct btree_iter *iter)
while (iter->nodes_locked)
btree_node_unlock(iter, __ffs(iter->nodes_locked));
+ iter->flags &= ~BTREE_ITER_UPTODATE;
+
return iter->flags & BTREE_ITER_ERROR ? -EIO : 0;
}
@@ -1006,16 +1008,30 @@ void bch2_btree_iter_set_pos_same_leaf(struct btree_iter *iter, struct bpos new_
iter->flags |= BTREE_ITER_AT_END_OF_LEAF;
iter->pos = new_pos;
+ iter->flags &= ~BTREE_ITER_UPTODATE;
}
void bch2_btree_iter_set_pos(struct btree_iter *iter, struct bpos new_pos)
{
EBUG_ON(bkey_cmp(new_pos, iter->pos) < 0); /* XXX handle this */
iter->pos = new_pos;
+ iter->flags &= ~BTREE_ITER_UPTODATE;
}
void bch2_btree_iter_advance_pos(struct btree_iter *iter)
{
+ if (iter->flags & BTREE_ITER_UPTODATE &&
+ !(iter->flags & BTREE_ITER_WITH_HOLES)) {
+ struct bkey_s_c k;
+
+ __btree_iter_advance(iter);
+ k = __btree_iter_peek(iter);
+ if (likely(k.k)) {
+ iter->pos = bkey_start_pos(k.k);
+ return;
+ }
+ }
+
/*
* We use iter->k instead of iter->pos for extents: iter->pos will be
* equal to the start of the extent we returned, but we need to advance
@@ -1032,6 +1048,7 @@ void bch2_btree_iter_rewind(struct btree_iter *iter, struct bpos pos)
BUG_ON(bkey_cmp(pos, iter->nodes[iter->level]->data->min_key) < 0);
iter->pos = pos;
+ iter->flags &= ~BTREE_ITER_UPTODATE;
__btree_iter_init(iter, iter->nodes[iter->level]);
}
@@ -1043,6 +1060,17 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
EBUG_ON(!!(iter->flags & BTREE_ITER_IS_EXTENTS) !=
(iter->btree_id == BTREE_ID_EXTENTS));
+ if (iter->flags & BTREE_ITER_UPTODATE) {
+ struct btree *b = iter->nodes[0];
+ struct bkey_packed *k =
+ __bch2_btree_node_iter_peek_all(&iter->node_iters[0], b);
+
+ return (struct bkey_s_c) {
+ .k = &iter->k,
+ .v = bkeyp_val(&b->format, k)
+ };
+ }
+
while (1) {
ret = bch2_btree_iter_traverse(iter);
if (unlikely(ret)) {
@@ -1058,7 +1086,9 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
*/
if (!(iter->flags & BTREE_ITER_IS_EXTENTS) ||
bkey_cmp(bkey_start_pos(k.k), iter->pos) > 0)
- bch2_btree_iter_set_pos(iter, bkey_start_pos(k.k));
+ iter->pos = bkey_start_pos(k.k);
+
+ iter->flags |= BTREE_ITER_UPTODATE;
return k;
}
@@ -1083,6 +1113,8 @@ struct bkey_s_c bch2_btree_iter_peek_with_holes(struct btree_iter *iter)
EBUG_ON(!!(iter->flags & BTREE_ITER_IS_EXTENTS) !=
(iter->btree_id == BTREE_ID_EXTENTS));
+ iter->flags &= ~BTREE_ITER_UPTODATE;
+
while (1) {
ret = bch2_btree_iter_traverse(iter);
if (unlikely(ret)) {
@@ -1131,12 +1163,15 @@ void __bch2_btree_iter_init(struct btree_iter *iter, struct bch_fs *c,
unsigned locks_want, unsigned depth,
unsigned flags)
{
+ EBUG_ON(depth >= BTREE_MAX_DEPTH);
+ EBUG_ON(locks_want > BTREE_MAX_DEPTH);
+
iter->c = c;
iter->pos = pos;
iter->flags = flags;
iter->btree_id = btree_id;
iter->level = depth;
- iter->locks_want = min(locks_want, BTREE_MAX_DEPTH);
+ iter->locks_want = locks_want;
iter->nodes_locked = 0;
iter->nodes_intent_locked = 0;
memset(iter->nodes, 0, sizeof(iter->nodes));