summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-03-25 15:34:48 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2019-03-25 15:53:07 -0400
commitfad2dc5030ca8a1430aed0ee0e728177dc784ee3 (patch)
treeb0b2a62729efcf2802c03017aebec665c3d4331b
parentffe09df1065dd1b326913b21381ed1ad35ab8ef9 (diff)
bcachefs: Btree iter improvements
-rw-r--r--fs/bcachefs/btree_iter.c94
-rw-r--r--fs/bcachefs/btree_iter.h3
-rw-r--r--fs/bcachefs/btree_types.h5
-rw-r--r--fs/bcachefs/btree_update_leaf.c5
4 files changed, 76 insertions, 31 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index 94b86ad6c7e6..d8559520898f 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -1670,8 +1670,8 @@ static inline unsigned btree_trans_iter_idx(struct btree_trans *trans,
{
ssize_t idx = iter - trans->iters;
- BUG_ON(idx < 0 || idx >= trans->nr_iters);
- BUG_ON(!(trans->iters_live & (1ULL << idx)));
+ EBUG_ON(idx < 0 || idx >= trans->nr_iters);
+ EBUG_ON(!(trans->iters_linked & (1ULL << idx)));
return idx;
}
@@ -1684,14 +1684,28 @@ void bch2_trans_iter_put(struct btree_trans *trans,
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,
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);
- trans->iters_linked &= ~(1ULL << idx);
- bch2_btree_iter_unlink(iter);
+void bch2_trans_iter_free_on_commit(struct btree_trans *trans,
+ struct btree_iter *iter)
+{
+ trans->iters_unlink_on_commit |=
+ 1ULL << btree_trans_iter_idx(trans, iter);
}
static int btree_trans_realloc_iters(struct btree_trans *trans,
@@ -1727,6 +1741,11 @@ success:
memcpy(new_updates, trans->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)
kfree(trans->iters);
@@ -1762,7 +1781,7 @@ void bch2_trans_preload_iters(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)
{
struct btree_iter *iter;
@@ -1770,9 +1789,14 @@ static struct btree_iter *__btree_trans_get_iter(struct btree_trans *trans,
BUG_ON(trans->nr_iters > BTREE_ITER_MAX);
- for (idx = 0; idx < trans->nr_iters; idx++)
- if (trans->iters[idx].id == iter_id)
+ for (idx = 0; idx < trans->nr_iters; idx++) {
+ iter = &trans->iters[idx];
+ if (iter_id
+ ? iter->id == iter_id
+ : (iter->btree_id == btree_id &&
+ !bkey_cmp(iter->pos, pos)))
goto found;
+ }
idx = -1;
found:
if (idx < 0) {
@@ -1803,8 +1827,10 @@ got_slot:
iter->flags |= flags & (BTREE_ITER_INTENT|BTREE_ITER_PREFETCH);
}
+ BUG_ON(iter->btree_id != btree_id);
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 &&
!(trans->iters_linked & (1 << idx)))
@@ -1827,7 +1853,7 @@ struct btree_iter *__bch2_trans_get_iter(struct btree_trans *trans,
u64 iter_id)
{
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))
bch2_btree_iter_set_pos(iter, pos);
@@ -1840,10 +1866,13 @@ struct btree_iter *__bch2_trans_copy_iter(struct btree_trans *trans,
{
struct btree_iter *iter =
__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);
+ }
return iter;
}
@@ -1893,10 +1922,21 @@ int bch2_trans_unlock(struct btree_trans *trans)
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)
{
- u64 linked_not_live;
- unsigned idx;
+ u64 iters_to_unlink;
btree_trans_verify(trans);
@@ -1908,22 +1948,20 @@ void __bch2_trans_begin(struct btree_trans *trans)
* further (allocated an iter with a higher idx) than where the iter
* was originally allocated:
*/
- while (1) {
- linked_not_live = trans->iters_linked & ~trans->iters_live;
- if (!linked_not_live)
- break;
+ iters_to_unlink = ~trans->iters_live &
+ ((1ULL << fls64(trans->iters_live)) - 1);
- idx = __ffs64(linked_not_live);
- if (1ULL << idx > trans->iters_live)
- break;
+ iters_to_unlink |= trans->iters_unlink_on_restart;
+ iters_to_unlink |= trans->iters_unlink_on_commit;
- trans->iters_linked ^= 1 << idx;
- bch2_btree_iter_unlink(&trans->iters[idx]);
- }
+ bch2_trans_unlink_iters(trans, iters_to_unlink);
- trans->iters_live = 0;
- trans->nr_updates = 0;
- trans->mem_top = 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->mem_top = 0;
btree_trans_verify(trans);
}
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h
index 7c49a661277a..5d1f7ff79f92 100644
--- a/fs/bcachefs/btree_iter.h
+++ b/fs/bcachefs/btree_iter.h
@@ -274,6 +274,9 @@ static inline int btree_iter_err(struct bkey_s_c k)
void bch2_trans_preload_iters(struct btree_trans *);
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_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 bpos, unsigned, u64);
diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h
index d566722aa482..e8158b127e31 100644
--- a/fs/bcachefs/btree_types.h
+++ b/fs/bcachefs/btree_types.h
@@ -275,8 +275,11 @@ struct btree_trans {
size_t nr_restarts;
u64 commit_start;
- u64 iters_live;
u64 iters_linked;
+ u64 iters_live;
+ u64 iters_touched;
+ u64 iters_unlink_on_restart;
+ u64 iters_unlink_on_commit;
u8 nr_iters;
u8 nr_updates;
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index e207b0997056..04b5699beed0 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -885,10 +885,11 @@ out_noupdates:
trans->commit_start = 0;
}
- trans->nr_updates = 0;
-
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;
err:
ret = bch2_trans_commit_error(trans, i, ret);