Commit 5df4be3f authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Btree iter improvements

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 03e183cb
...@@ -1671,8 +1671,8 @@ static inline unsigned btree_trans_iter_idx(struct btree_trans *trans, ...@@ -1671,8 +1671,8 @@ static inline unsigned btree_trans_iter_idx(struct btree_trans *trans,
{ {
ssize_t idx = iter - trans->iters; ssize_t idx = iter - trans->iters;
BUG_ON(idx < 0 || idx >= trans->nr_iters); EBUG_ON(idx < 0 || idx >= trans->nr_iters);
BUG_ON(!(trans->iters_live & (1ULL << idx))); EBUG_ON(!(trans->iters_linked & (1ULL << idx)));
return idx; return idx;
} }
...@@ -1685,14 +1685,28 @@ void bch2_trans_iter_put(struct btree_trans *trans, ...@@ -1685,14 +1685,28 @@ void bch2_trans_iter_put(struct btree_trans *trans,
trans->iters_live &= ~(1ULL << idx); trans->iters_live &= ~(1ULL << idx);
} }
static inline void __bch2_trans_iter_free(struct btree_trans *trans,
unsigned idx)
{
trans->iters_linked &= ~(1ULL << idx);
trans->iters_live &= ~(1ULL << idx);
trans->iters_touched &= ~(1ULL << idx);
trans->iters_unlink_on_restart &= ~(1ULL << idx);
trans->iters_unlink_on_commit &= ~(1ULL << idx);
bch2_btree_iter_unlink(&trans->iters[idx]);
}
void bch2_trans_iter_free(struct btree_trans *trans, void bch2_trans_iter_free(struct btree_trans *trans,
struct btree_iter *iter) struct btree_iter *iter)
{ {
ssize_t idx = btree_trans_iter_idx(trans, iter); __bch2_trans_iter_free(trans, btree_trans_iter_idx(trans, iter));
}
trans->iters_live &= ~(1ULL << idx); void bch2_trans_iter_free_on_commit(struct btree_trans *trans,
trans->iters_linked &= ~(1ULL << idx); struct btree_iter *iter)
bch2_btree_iter_unlink(iter); {
trans->iters_unlink_on_commit |=
1ULL << btree_trans_iter_idx(trans, iter);
} }
static int btree_trans_realloc_iters(struct btree_trans *trans, static int btree_trans_realloc_iters(struct btree_trans *trans,
...@@ -1728,6 +1742,11 @@ static int btree_trans_realloc_iters(struct btree_trans *trans, ...@@ -1728,6 +1742,11 @@ static int btree_trans_realloc_iters(struct btree_trans *trans,
memcpy(new_updates, trans->updates, memcpy(new_updates, trans->updates,
sizeof(struct btree_insert_entry) * trans->nr_updates); sizeof(struct btree_insert_entry) * trans->nr_updates);
if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG))
memset(trans->iters, POISON_FREE,
sizeof(struct btree_iter) * trans->nr_iters +
sizeof(struct btree_insert_entry) * trans->nr_iters);
if (trans->iters != trans->iters_onstack) if (trans->iters != trans->iters_onstack)
kfree(trans->iters); kfree(trans->iters);
...@@ -1763,7 +1782,7 @@ void bch2_trans_preload_iters(struct btree_trans *trans) ...@@ -1763,7 +1782,7 @@ void bch2_trans_preload_iters(struct btree_trans *trans)
} }
static struct btree_iter *__btree_trans_get_iter(struct btree_trans *trans, static struct btree_iter *__btree_trans_get_iter(struct btree_trans *trans,
unsigned btree_id, unsigned btree_id, struct bpos pos,
unsigned flags, u64 iter_id) unsigned flags, u64 iter_id)
{ {
struct btree_iter *iter; struct btree_iter *iter;
...@@ -1771,9 +1790,14 @@ static struct btree_iter *__btree_trans_get_iter(struct btree_trans *trans, ...@@ -1771,9 +1790,14 @@ static struct btree_iter *__btree_trans_get_iter(struct btree_trans *trans,
BUG_ON(trans->nr_iters > BTREE_ITER_MAX); BUG_ON(trans->nr_iters > BTREE_ITER_MAX);
for (idx = 0; idx < trans->nr_iters; idx++) for (idx = 0; idx < trans->nr_iters; idx++) {
if (trans->iters[idx].id == iter_id) iter = &trans->iters[idx];
if (iter_id
? iter->id == iter_id
: (iter->btree_id == btree_id &&
!bkey_cmp(iter->pos, pos)))
goto found; goto found;
}
idx = -1; idx = -1;
found: found:
if (idx < 0) { if (idx < 0) {
...@@ -1804,8 +1828,10 @@ static struct btree_iter *__btree_trans_get_iter(struct btree_trans *trans, ...@@ -1804,8 +1828,10 @@ static struct btree_iter *__btree_trans_get_iter(struct btree_trans *trans,
iter->flags |= flags & (BTREE_ITER_INTENT|BTREE_ITER_PREFETCH); iter->flags |= flags & (BTREE_ITER_INTENT|BTREE_ITER_PREFETCH);
} }
BUG_ON(iter->btree_id != btree_id);
BUG_ON(trans->iters_live & (1ULL << idx)); BUG_ON(trans->iters_live & (1ULL << idx));
trans->iters_live |= 1ULL << idx; trans->iters_live |= 1ULL << idx;
trans->iters_touched |= 1ULL << idx;
if (trans->iters_linked && if (trans->iters_linked &&
!(trans->iters_linked & (1 << idx))) !(trans->iters_linked & (1 << idx)))
...@@ -1828,7 +1854,7 @@ struct btree_iter *__bch2_trans_get_iter(struct btree_trans *trans, ...@@ -1828,7 +1854,7 @@ struct btree_iter *__bch2_trans_get_iter(struct btree_trans *trans,
u64 iter_id) u64 iter_id)
{ {
struct btree_iter *iter = struct btree_iter *iter =
__btree_trans_get_iter(trans, btree_id, flags, iter_id); __btree_trans_get_iter(trans, btree_id, pos, flags, iter_id);
if (!IS_ERR(iter)) if (!IS_ERR(iter))
bch2_btree_iter_set_pos(iter, pos); bch2_btree_iter_set_pos(iter, pos);
...@@ -1841,10 +1867,13 @@ struct btree_iter *__bch2_trans_copy_iter(struct btree_trans *trans, ...@@ -1841,10 +1867,13 @@ struct btree_iter *__bch2_trans_copy_iter(struct btree_trans *trans,
{ {
struct btree_iter *iter = struct btree_iter *iter =
__btree_trans_get_iter(trans, src->btree_id, __btree_trans_get_iter(trans, src->btree_id,
src->flags, iter_id); POS_MIN, src->flags, iter_id);
if (!IS_ERR(iter)) if (!IS_ERR(iter)) {
trans->iters_unlink_on_restart |=
1ULL << btree_trans_iter_idx(trans, iter);
bch2_btree_iter_copy(iter, src); bch2_btree_iter_copy(iter, src);
}
return iter; return iter;
} }
...@@ -1894,10 +1923,21 @@ int bch2_trans_unlock(struct btree_trans *trans) ...@@ -1894,10 +1923,21 @@ int bch2_trans_unlock(struct btree_trans *trans)
return ret; return ret;
} }
inline void bch2_trans_unlink_iters(struct btree_trans *trans, u64 iters)
{
iters &= trans->iters_linked;
while (iters) {
unsigned idx = __ffs64(iters);
iters &= ~(1ULL << idx);
__bch2_trans_iter_free(trans, idx);
}
}
void __bch2_trans_begin(struct btree_trans *trans) void __bch2_trans_begin(struct btree_trans *trans)
{ {
u64 linked_not_live; u64 iters_to_unlink;
unsigned idx;
btree_trans_verify(trans); btree_trans_verify(trans);
...@@ -1909,20 +1949,18 @@ void __bch2_trans_begin(struct btree_trans *trans) ...@@ -1909,20 +1949,18 @@ void __bch2_trans_begin(struct btree_trans *trans)
* further (allocated an iter with a higher idx) than where the iter * further (allocated an iter with a higher idx) than where the iter
* was originally allocated: * was originally allocated:
*/ */
while (1) { iters_to_unlink = ~trans->iters_live &
linked_not_live = trans->iters_linked & ~trans->iters_live; ((1ULL << fls64(trans->iters_live)) - 1);
if (!linked_not_live)
break;
idx = __ffs64(linked_not_live); iters_to_unlink |= trans->iters_unlink_on_restart;
if (1ULL << idx > trans->iters_live) iters_to_unlink |= trans->iters_unlink_on_commit;
break;
trans->iters_linked ^= 1 << idx; bch2_trans_unlink_iters(trans, iters_to_unlink);
bch2_btree_iter_unlink(&trans->iters[idx]);
}
trans->iters_live = 0; trans->iters_live = 0;
trans->iters_touched = 0;
trans->iters_unlink_on_restart = 0;
trans->iters_unlink_on_commit = 0;
trans->nr_updates = 0; trans->nr_updates = 0;
trans->mem_top = 0; trans->mem_top = 0;
......
...@@ -273,6 +273,9 @@ static inline int btree_iter_err(struct bkey_s_c k) ...@@ -273,6 +273,9 @@ static inline int btree_iter_err(struct bkey_s_c k)
void bch2_trans_preload_iters(struct btree_trans *); void bch2_trans_preload_iters(struct btree_trans *);
void bch2_trans_iter_put(struct btree_trans *, struct btree_iter *); void bch2_trans_iter_put(struct btree_trans *, struct btree_iter *);
void bch2_trans_iter_free(struct btree_trans *, struct btree_iter *); void bch2_trans_iter_free(struct btree_trans *, struct btree_iter *);
void bch2_trans_iter_free_on_commit(struct btree_trans *, struct btree_iter *);
void bch2_trans_unlink_iters(struct btree_trans *, u64);
struct btree_iter *__bch2_trans_get_iter(struct btree_trans *, enum btree_id, struct btree_iter *__bch2_trans_get_iter(struct btree_trans *, enum btree_id,
struct bpos, unsigned, u64); struct bpos, unsigned, u64);
......
...@@ -276,8 +276,11 @@ struct btree_trans { ...@@ -276,8 +276,11 @@ struct btree_trans {
size_t nr_restarts; size_t nr_restarts;
u64 commit_start; u64 commit_start;
u64 iters_live;
u64 iters_linked; u64 iters_linked;
u64 iters_live;
u64 iters_touched;
u64 iters_unlink_on_restart;
u64 iters_unlink_on_commit;
u8 nr_iters; u8 nr_iters;
u8 nr_updates; u8 nr_updates;
......
...@@ -886,10 +886,11 @@ int bch2_trans_commit(struct btree_trans *trans, ...@@ -886,10 +886,11 @@ int bch2_trans_commit(struct btree_trans *trans,
trans->commit_start = 0; trans->commit_start = 0;
} }
trans->nr_updates = 0;
BUG_ON(!(trans->flags & BTREE_INSERT_ATOMIC) && ret == -EINTR); BUG_ON(!(trans->flags & BTREE_INSERT_ATOMIC) && ret == -EINTR);
bch2_trans_unlink_iters(trans, trans->iters_unlink_on_commit);
trans->nr_updates = 0;
return ret; return ret;
err: err:
ret = bch2_trans_commit_error(trans, i, ret); ret = bch2_trans_commit_error(trans, i, ret);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment