summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-03-20 15:12:05 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2021-03-24 19:24:30 -0400
commit0f59bfd5b9acc4cc1386b946d8694cbce8ed1b58 (patch)
tree3221ff53f9c46a5cbee8b865482f20a4a5b829f9
parenta154da5a1ee74c085c2066c8d23839aeec437a49 (diff)
bcachefs: Child btree iterators
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/btree_iter.c60
-rw-r--r--fs/bcachefs/btree_iter.h6
-rw-r--r--fs/bcachefs/btree_types.h18
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