bcachefs: Child btree iterators
This adds the ability for btree iterators to own child iterators - to be used by an upcoming rework of bch2_btree_iter_peek_slot(), so we can scan forwards while maintaining our current position. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
This commit is contained in:
parent
c205321b12
commit
509d3e0a8d
@ -18,6 +18,9 @@
|
|||||||
#include <linux/prefetch.h>
|
#include <linux/prefetch.h>
|
||||||
|
|
||||||
static void btree_iter_set_search_pos(struct btree_iter *, struct bpos);
|
static void btree_iter_set_search_pos(struct btree_iter *, struct bpos);
|
||||||
|
static struct btree_iter *btree_iter_child_alloc(struct btree_iter *, unsigned long);
|
||||||
|
static struct btree_iter *btree_trans_iter_alloc(struct btree_trans *);
|
||||||
|
static void btree_iter_copy(struct btree_iter *, struct btree_iter *);
|
||||||
|
|
||||||
static inline struct bpos bkey_successor(struct btree_iter *iter, struct bpos p)
|
static inline struct bpos bkey_successor(struct btree_iter *iter, struct bpos p)
|
||||||
{
|
{
|
||||||
@ -1967,9 +1970,39 @@ static inline void bch2_btree_iter_init(struct btree_trans *trans,
|
|||||||
|
|
||||||
/* new transactional stuff: */
|
/* new transactional stuff: */
|
||||||
|
|
||||||
|
static void btree_iter_child_free(struct btree_iter *iter)
|
||||||
|
{
|
||||||
|
struct btree_iter *child = btree_iter_child(iter);
|
||||||
|
|
||||||
|
if (child) {
|
||||||
|
bch2_trans_iter_free(iter->trans, child);
|
||||||
|
iter->child_idx = U8_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct btree_iter *btree_iter_child_alloc(struct btree_iter *iter,
|
||||||
|
unsigned long ip)
|
||||||
|
{
|
||||||
|
struct btree_trans *trans = iter->trans;
|
||||||
|
struct btree_iter *child = btree_iter_child(iter);
|
||||||
|
|
||||||
|
if (!child) {
|
||||||
|
child = btree_trans_iter_alloc(trans);
|
||||||
|
child->ip_allocated = ip;
|
||||||
|
iter->child_idx = child->idx;
|
||||||
|
|
||||||
|
trans->iters_live |= 1ULL << child->idx;
|
||||||
|
trans->iters_touched |= 1ULL << child->idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void __bch2_trans_iter_free(struct btree_trans *trans,
|
static inline void __bch2_trans_iter_free(struct btree_trans *trans,
|
||||||
unsigned idx)
|
unsigned idx)
|
||||||
{
|
{
|
||||||
|
btree_iter_child_free(&trans->iters[idx]);
|
||||||
|
|
||||||
__bch2_btree_iter_unlock(&trans->iters[idx]);
|
__bch2_btree_iter_unlock(&trans->iters[idx]);
|
||||||
trans->iters_linked &= ~(1ULL << idx);
|
trans->iters_linked &= ~(1ULL << idx);
|
||||||
trans->iters_live &= ~(1ULL << idx);
|
trans->iters_live &= ~(1ULL << idx);
|
||||||
@ -2037,6 +2070,7 @@ static void btree_trans_iter_alloc_fail(struct btree_trans *trans)
|
|||||||
|
|
||||||
static struct btree_iter *btree_trans_iter_alloc(struct btree_trans *trans)
|
static struct btree_iter *btree_trans_iter_alloc(struct btree_trans *trans)
|
||||||
{
|
{
|
||||||
|
struct btree_iter *iter;
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
|
|
||||||
if (unlikely(trans->iters_linked ==
|
if (unlikely(trans->iters_linked ==
|
||||||
@ -2044,21 +2078,28 @@ static struct btree_iter *btree_trans_iter_alloc(struct btree_trans *trans)
|
|||||||
btree_trans_iter_alloc_fail(trans);
|
btree_trans_iter_alloc_fail(trans);
|
||||||
|
|
||||||
idx = __ffs64(~trans->iters_linked);
|
idx = __ffs64(~trans->iters_linked);
|
||||||
|
iter = &trans->iters[idx];
|
||||||
|
|
||||||
|
iter->trans = trans;
|
||||||
|
iter->idx = idx;
|
||||||
|
iter->child_idx = U8_MAX;
|
||||||
|
iter->flags = 0;
|
||||||
|
iter->nodes_locked = 0;
|
||||||
|
iter->nodes_intent_locked = 0;
|
||||||
trans->iters_linked |= 1ULL << idx;
|
trans->iters_linked |= 1ULL << idx;
|
||||||
trans->iters[idx].idx = idx;
|
return iter;
|
||||||
trans->iters[idx].flags = 0;
|
|
||||||
return &trans->iters[idx];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void btree_iter_copy(struct btree_iter *dst,
|
static void btree_iter_copy(struct btree_iter *dst, struct btree_iter *src)
|
||||||
struct btree_iter *src)
|
|
||||||
{
|
{
|
||||||
unsigned i, idx = dst->idx;
|
unsigned i, offset = offsetof(struct btree_iter, flags);
|
||||||
|
|
||||||
*dst = *src;
|
__bch2_btree_iter_unlock(dst);
|
||||||
dst->idx = idx;
|
btree_iter_child_free(dst);
|
||||||
dst->flags &= ~BTREE_ITER_KEEP_UNTIL_COMMIT;
|
|
||||||
|
memcpy((void *) dst + offset,
|
||||||
|
(void *) src + offset,
|
||||||
|
sizeof(struct btree_iter) - offset);
|
||||||
|
|
||||||
for (i = 0; i < BTREE_MAX_DEPTH; i++)
|
for (i = 0; i < BTREE_MAX_DEPTH; i++)
|
||||||
if (btree_node_locked(dst, i))
|
if (btree_node_locked(dst, i))
|
||||||
@ -2365,6 +2406,13 @@ int bch2_trans_exit(struct btree_trans *trans)
|
|||||||
bch2_trans_unlock(trans);
|
bch2_trans_unlock(trans);
|
||||||
|
|
||||||
#ifdef CONFIG_BCACHEFS_DEBUG
|
#ifdef CONFIG_BCACHEFS_DEBUG
|
||||||
|
if (trans->iters_live) {
|
||||||
|
struct btree_iter *iter;
|
||||||
|
|
||||||
|
trans_for_each_iter(trans, iter)
|
||||||
|
btree_iter_child_free(iter);
|
||||||
|
}
|
||||||
|
|
||||||
if (trans->iters_live) {
|
if (trans->iters_live) {
|
||||||
struct btree_iter *iter;
|
struct btree_iter *iter;
|
||||||
|
|
||||||
|
@ -181,6 +181,12 @@ static inline void bch2_btree_iter_set_pos(struct btree_iter *iter, struct bpos
|
|||||||
iter->should_be_locked = false;
|
iter->should_be_locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct btree_iter *btree_iter_child(struct btree_iter *iter)
|
||||||
|
{
|
||||||
|
return iter->child_idx == U8_MAX ? NULL
|
||||||
|
: iter->trans->iters + iter->child_idx;
|
||||||
|
}
|
||||||
|
|
||||||
/* Sort order for locking btree iterators: */
|
/* Sort order for locking btree iterators: */
|
||||||
static inline int btree_iter_lock_cmp(const struct btree_iter *l,
|
static inline int btree_iter_lock_cmp(const struct btree_iter *l,
|
||||||
const struct btree_iter *r)
|
const struct btree_iter *r)
|
||||||
|
@ -241,15 +241,20 @@ enum btree_iter_uptodate {
|
|||||||
*/
|
*/
|
||||||
struct btree_iter {
|
struct btree_iter {
|
||||||
struct btree_trans *trans;
|
struct btree_trans *trans;
|
||||||
struct bpos pos;
|
unsigned long ip_allocated;
|
||||||
/* what we're searching for/what the iterator actually points to: */
|
|
||||||
struct bpos real_pos;
|
u8 idx;
|
||||||
struct bpos pos_after_commit;
|
u8 child_idx;
|
||||||
|
|
||||||
|
/* btree_iter_copy starts here: */
|
||||||
|
u16 flags;
|
||||||
|
|
||||||
/* When we're filtering by snapshot, the snapshot ID we're looking for: */
|
/* When we're filtering by snapshot, the snapshot ID we're looking for: */
|
||||||
unsigned snapshot;
|
unsigned snapshot;
|
||||||
|
|
||||||
u16 flags;
|
struct bpos pos;
|
||||||
u8 idx;
|
struct bpos real_pos;
|
||||||
|
struct bpos pos_after_commit;
|
||||||
|
|
||||||
enum btree_id btree_id:4;
|
enum btree_id btree_id:4;
|
||||||
enum btree_iter_uptodate uptodate:3;
|
enum btree_iter_uptodate uptodate:3;
|
||||||
@ -276,7 +281,6 @@ struct btree_iter {
|
|||||||
* bch2_btree_iter_next_slot() can correctly advance pos.
|
* bch2_btree_iter_next_slot() can correctly advance pos.
|
||||||
*/
|
*/
|
||||||
struct bkey k;
|
struct bkey k;
|
||||||
unsigned long ip_allocated;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline enum btree_iter_type
|
static inline enum btree_iter_type
|
||||||
|
Loading…
x
Reference in New Issue
Block a user