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.c106
1 files changed, 68 insertions, 38 deletions
diff --git a/libbcachefs/btree_iter.c b/libbcachefs/btree_iter.c
index 0b28082e..e5da186b 100644
--- a/libbcachefs/btree_iter.c
+++ b/libbcachefs/btree_iter.c
@@ -161,8 +161,9 @@ bool __bch2_btree_node_lock(struct btree *b, struct bpos pos,
*/
if (type == SIX_LOCK_intent &&
linked->nodes_locked != linked->nodes_intent_locked) {
- linked->locks_want = max(linked->locks_want,
- iter->locks_want);
+ linked->locks_want = max_t(unsigned,
+ linked->locks_want,
+ iter->locks_want);
return false;
}
@@ -177,8 +178,9 @@ bool __bch2_btree_node_lock(struct btree *b, struct bpos pos,
*/
if (linked->btree_id == iter->btree_id &&
level > __fls(linked->nodes_locked)) {
- linked->locks_want = max(linked->locks_want,
- iter->locks_want);
+ linked->locks_want = max_t(unsigned,
+ linked->locks_want,
+ iter->locks_want);
return false;
}
}
@@ -247,12 +249,10 @@ fail:
static int __bch2_btree_iter_unlock(struct btree_iter *iter)
{
- BUG_ON(iter->error == -EINTR);
-
while (iter->nodes_locked)
btree_node_unlock(iter, __ffs(iter->nodes_locked));
- return iter->error;
+ return iter->flags & BTREE_ITER_ERROR ? -EIO : 0;
}
int bch2_btree_iter_unlock(struct btree_iter *iter)
@@ -285,7 +285,7 @@ static void __bch2_btree_iter_verify(struct btree_iter *iter,
? bch2_btree_node_iter_prev(&tmp, b)
: bch2_btree_node_iter_prev_all(&tmp, b);
if (k && btree_iter_pos_cmp_packed(b, &iter->pos, k,
- iter->is_extents)) {
+ iter->flags & BTREE_ITER_IS_EXTENTS)) {
char buf[100];
struct bkey uk = bkey_unpack_key(b, k);
@@ -296,7 +296,7 @@ static void __bch2_btree_iter_verify(struct btree_iter *iter,
k = bch2_btree_node_iter_peek_all(node_iter, b);
if (k && !btree_iter_pos_cmp_packed(b, &iter->pos, k,
- iter->is_extents)) {
+ iter->flags & BTREE_ITER_IS_EXTENTS)) {
char buf[100];
struct bkey uk = bkey_unpack_key(b, k);
@@ -340,7 +340,7 @@ static void __bch2_btree_node_iter_fix(struct btree_iter *iter,
/* didn't find the bset in the iterator - might have to readd it: */
if (new_u64s &&
btree_iter_pos_cmp_packed(b, &iter->pos, where,
- iter->is_extents))
+ iter->flags & BTREE_ITER_IS_EXTENTS))
bch2_btree_node_iter_push(node_iter, b, where, end);
return;
found:
@@ -352,7 +352,7 @@ found:
if (new_u64s &&
btree_iter_pos_cmp_packed(b, &iter->pos, where,
- iter->is_extents)) {
+ iter->flags & BTREE_ITER_IS_EXTENTS)) {
set->k = offset;
bch2_btree_node_iter_sort(node_iter, b);
} else if (set->k < offset + clobber_u64s) {
@@ -388,7 +388,7 @@ found:
*/
if (b->level && new_u64s && !bkey_deleted(where) &&
btree_iter_pos_cmp_packed(b, &iter->pos, where,
- iter->is_extents)) {
+ iter->flags & BTREE_ITER_IS_EXTENTS)) {
struct bset_tree *t;
struct bkey_packed *k;
@@ -535,9 +535,9 @@ static void btree_iter_verify_new_node(struct btree_iter *iter, struct btree *b)
static inline void __btree_iter_init(struct btree_iter *iter,
struct btree *b)
{
- bch2_btree_node_iter_init(&iter->node_iters[b->level], b,
- iter->pos, iter->is_extents,
- btree_node_is_extents(b));
+ bch2_btree_node_iter_init(&iter->node_iters[b->level], b, iter->pos,
+ iter->flags & BTREE_ITER_IS_EXTENTS,
+ btree_node_is_extents(b));
/* Skip to first non whiteout: */
if (b->level)
@@ -549,7 +549,8 @@ static inline bool btree_iter_pos_in_node(struct btree_iter *iter,
{
return iter->btree_id == b->btree_id &&
bkey_cmp(iter->pos, b->data->min_key) >= 0 &&
- btree_iter_pos_cmp(iter->pos, &b->key.k, iter->is_extents);
+ btree_iter_pos_cmp(iter->pos, &b->key.k,
+ iter->flags & BTREE_ITER_IS_EXTENTS);
}
static inline void btree_iter_node_set(struct btree_iter *iter,
@@ -695,6 +696,26 @@ static inline int btree_iter_lock_root(struct btree_iter *iter,
}
}
+noinline
+static void btree_iter_prefetch(struct btree_iter *iter)
+{
+ struct btree *b = iter->nodes[iter->level + 1];
+ struct btree_node_iter node_iter = iter->node_iters[iter->level + 1];
+ struct bkey_packed *k;
+ BKEY_PADDED(k) tmp;
+ unsigned nr = iter->level ? 1 : 8;
+
+ while (nr) {
+ bch2_btree_node_iter_advance(&node_iter, b);
+ k = bch2_btree_node_iter_peek(&node_iter, b);
+ if (!k)
+ break;
+
+ bch2_bkey_unpack(b, &tmp.k, k);
+ bch2_btree_node_prefetch(iter, &tmp.k, iter->level);
+ }
+}
+
static inline int btree_iter_down(struct btree_iter *iter)
{
struct btree *b;
@@ -712,6 +733,10 @@ static inline int btree_iter_down(struct btree_iter *iter)
iter->level = level;
mark_btree_node_locked(iter, level, lock_type);
btree_iter_node_set(iter, b);
+
+ if (iter->flags & BTREE_ITER_PREFETCH)
+ btree_iter_prefetch(iter);
+
return 0;
}
@@ -791,7 +816,7 @@ out:
io_error:
BUG_ON(ret != -EIO);
- iter->error = ret;
+ iter->flags |= BTREE_ITER_ERROR;
iter->nodes[iter->level] = NULL;
goto out;
}
@@ -834,7 +859,7 @@ int __must_check __bch2_btree_iter_traverse(struct btree_iter *iter)
bch2_btree_node_relock(iter, iter->level) &&
btree_iter_pos_cmp(iter->pos,
&iter->nodes[iter->level]->key.k,
- iter->is_extents)))
+ iter->flags & BTREE_ITER_IS_EXTENTS)))
btree_iter_up(iter);
/*
@@ -845,7 +870,8 @@ int __must_check __bch2_btree_iter_traverse(struct btree_iter *iter)
struct bkey_s_c k;
while ((k = __btree_iter_peek_all(iter)).k &&
- !btree_iter_pos_cmp(iter->pos, k.k, iter->is_extents))
+ !btree_iter_pos_cmp(iter->pos, k.k,
+ iter->flags & BTREE_ITER_IS_EXTENTS))
__btree_iter_advance(iter);
}
@@ -875,7 +901,7 @@ int __must_check bch2_btree_iter_traverse(struct btree_iter *iter)
if (unlikely(!iter->nodes[iter->level]))
return 0;
- iter->at_end_of_leaf = false;
+ iter->flags &= ~BTREE_ITER_AT_END_OF_LEAF;
ret = __bch2_btree_iter_traverse(iter);
if (unlikely(ret))
@@ -891,7 +917,7 @@ struct btree *bch2_btree_iter_peek_node(struct btree_iter *iter)
struct btree *b;
int ret;
- EBUG_ON(iter->is_extents);
+ EBUG_ON(iter->flags & BTREE_ITER_IS_EXTENTS);
ret = bch2_btree_iter_traverse(iter);
if (ret)
@@ -912,7 +938,7 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter, unsigned depth)
struct btree *b;
int ret;
- EBUG_ON(iter->is_extents);
+ EBUG_ON(iter->flags & BTREE_ITER_IS_EXTENTS);
btree_iter_up(iter);
@@ -964,12 +990,13 @@ void bch2_btree_iter_set_pos_same_leaf(struct btree_iter *iter, struct bpos new_
while ((k = bch2_btree_node_iter_peek_all(node_iter, b)) &&
!btree_iter_pos_cmp_packed(b, &new_pos, k,
- iter->is_extents))
+ iter->flags & BTREE_ITER_IS_EXTENTS))
bch2_btree_node_iter_advance(node_iter, b);
if (!k &&
- !btree_iter_pos_cmp(new_pos, &b->key.k, iter->is_extents))
- iter->at_end_of_leaf = true;
+ !btree_iter_pos_cmp(new_pos, &b->key.k,
+ iter->flags & BTREE_ITER_IS_EXTENTS))
+ iter->flags |= BTREE_ITER_AT_END_OF_LEAF;
iter->pos = new_pos;
}
@@ -1006,6 +1033,9 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
struct bkey_s_c k;
int ret;
+ EBUG_ON(!!(iter->flags & BTREE_ITER_IS_EXTENTS) !=
+ (iter->btree_id == BTREE_ID_EXTENTS));
+
while (1) {
ret = bch2_btree_iter_traverse(iter);
if (unlikely(ret)) {
@@ -1019,7 +1049,7 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
* iter->pos should always be equal to the key we just
* returned - except extents can straddle iter->pos:
*/
- if (!iter->is_extents ||
+ 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));
return k;
@@ -1043,6 +1073,9 @@ struct bkey_s_c bch2_btree_iter_peek_with_holes(struct btree_iter *iter)
struct bkey n;
int ret;
+ EBUG_ON(!!(iter->flags & BTREE_ITER_IS_EXTENTS) !=
+ (iter->btree_id == BTREE_ID_EXTENTS));
+
while (1) {
ret = bch2_btree_iter_traverse(iter);
if (unlikely(ret)) {
@@ -1057,7 +1090,7 @@ recheck:
bkey_init(&n);
n.p = iter->pos;
- if (iter->is_extents) {
+ if (iter->flags & BTREE_ITER_IS_EXTENTS) {
if (n.p.offset == KEY_OFFSET_MAX) {
iter->pos = bkey_successor(iter->pos);
goto recheck;
@@ -1087,21 +1120,18 @@ recheck:
}
void __bch2_btree_iter_init(struct btree_iter *iter, struct bch_fs *c,
- enum btree_id btree_id, struct bpos pos,
- unsigned locks_want, unsigned depth)
+ enum btree_id btree_id, struct bpos pos,
+ unsigned locks_want, unsigned depth,
+ unsigned flags)
{
+ iter->c = c;
+ iter->pos = pos;
+ iter->flags = flags;
+ iter->btree_id = btree_id;
iter->level = depth;
- /* bch2_bkey_ops isn't used much, this would be a cache miss */
- /* iter->is_extents = bch2_bkey_ops[btree_id]->is_extents; */
- iter->is_extents = btree_id == BTREE_ID_EXTENTS;
+ iter->locks_want = min(locks_want, BTREE_MAX_DEPTH);
iter->nodes_locked = 0;
iter->nodes_intent_locked = 0;
- iter->locks_want = min(locks_want, BTREE_MAX_DEPTH);
- iter->btree_id = btree_id;
- iter->at_end_of_leaf = 0;
- iter->error = 0;
- iter->c = c;
- iter->pos = pos;
memset(iter->nodes, 0, sizeof(iter->nodes));
iter->nodes[iter->level] = BTREE_ITER_NOT_END;
iter->next = iter;