diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-03-20 15:12:05 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2021-03-24 19:24:30 -0400 |
commit | 0f59bfd5b9acc4cc1386b946d8694cbce8ed1b58 (patch) | |
tree | 3221ff53f9c46a5cbee8b865482f20a4a5b829f9 | |
parent | a154da5a1ee74c085c2066c8d23839aeec437a49 (diff) |
bcachefs: Child btree iterators
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/btree_iter.c | 60 | ||||
-rw-r--r-- | fs/bcachefs/btree_iter.h | 6 | ||||
-rw-r--r-- | fs/bcachefs/btree_types.h | 18 |
3 files changed, 67 insertions, 17 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 9771bd1a10e0..debe5f0c2285 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -17,6 +17,9 @@ #include <trace/events/bcachefs.h> 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) { @@ -1904,6 +1907,34 @@ static inline void bch2_btree_iter_init(struct btree_trans *trans, /* 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, unsigned idx) { @@ -1924,6 +1955,8 @@ int bch2_trans_iter_put(struct btree_trans *trans, BUG_ON(trans->iters + iter->idx != iter); BUG_ON(!btree_iter_live(trans, iter)); + btree_iter_child_free(iter); + ret = btree_iter_err(iter); if (!(trans->iters_touched & (1ULL << iter->idx)) && @@ -1974,6 +2007,7 @@ static void btree_trans_iter_alloc_fail(struct btree_trans *trans) static struct btree_iter *btree_trans_iter_alloc(struct btree_trans *trans) { + struct btree_iter *iter; unsigned idx; if (unlikely(trans->iters_linked == @@ -1981,21 +2015,27 @@ static struct btree_iter *btree_trans_iter_alloc(struct btree_trans *trans) btree_trans_iter_alloc_fail(trans); 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[idx].idx = idx; - trans->iters[idx].flags = 0; - return &trans->iters[idx]; + return iter; } -static inline void btree_iter_copy(struct btree_iter *dst, - struct btree_iter *src) +static void btree_iter_copy(struct btree_iter *dst, struct btree_iter *src) { - unsigned i, idx = dst->idx; + unsigned i; - *dst = *src; - dst->idx = idx; - dst->flags &= ~BTREE_ITER_KEEP_UNTIL_COMMIT; + __bch2_btree_iter_unlock(dst); + btree_iter_child_free(dst); + + memcpy(&dst->flags, &src->flags, + sizeof(struct btree_iter) - offsetof(struct btree_iter, flags)); for (i = 0; i < BTREE_MAX_DEPTH; i++) if (btree_node_locked(dst, i)) diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h index e6dbda8d91ea..802f0cc853fc 100644 --- a/fs/bcachefs/btree_iter.h +++ b/fs/bcachefs/btree_iter.h @@ -179,6 +179,12 @@ static inline void bch2_btree_iter_set_pos(struct btree_iter *iter, struct bpos iter->k.p = iter->pos = new_pos; } +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: */ static inline int btree_iter_lock_cmp(const struct btree_iter *l, const struct btree_iter *r) diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index 3cf658d15445..a7f0bb6e0b2e 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -242,15 +242,20 @@ enum btree_iter_uptodate { */ struct btree_iter { struct btree_trans *trans; - struct bpos pos; - /* what we're searching for/what the iterator actually points to: */ - struct bpos real_pos; - struct bpos pos_after_commit; + unsigned long ip_allocated; + + u8 idx; + u8 child_idx; + + /* btree_iter_copy starts here: */ + u16 flags; + /* When we're filtering by snapshot, the snapshot ID we're looking for: */ unsigned snapshot; - u16 flags; - u8 idx; + struct bpos pos; + struct bpos real_pos; + struct bpos pos_after_commit; enum btree_id btree_id:4; enum btree_iter_uptodate uptodate:4; @@ -271,7 +276,6 @@ struct btree_iter { * bch2_btree_iter_next_slot() can correctly advance pos. */ struct bkey k; - unsigned long ip_allocated; }; static inline enum btree_iter_type |