summaryrefslogtreecommitdiff
path: root/libbcachefs/btree_update_leaf.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/btree_update_leaf.c')
-rw-r--r--libbcachefs/btree_update_leaf.c99
1 files changed, 84 insertions, 15 deletions
diff --git a/libbcachefs/btree_update_leaf.c b/libbcachefs/btree_update_leaf.c
index 588a1997..a481b0d6 100644
--- a/libbcachefs/btree_update_leaf.c
+++ b/libbcachefs/btree_update_leaf.c
@@ -309,8 +309,10 @@ static inline int do_btree_insert_at(struct btree_insert *trans,
unsigned u64s;
int ret;
- trans_for_each_entry(trans, i)
+ trans_for_each_entry(trans, i) {
BUG_ON(i->done);
+ BUG_ON(i->iter->uptodate >= BTREE_ITER_NEED_RELOCK);
+ }
u64s = 0;
trans_for_each_entry(trans, i)
@@ -330,6 +332,7 @@ static inline int do_btree_insert_at(struct btree_insert *trans,
if (race_fault()) {
ret = -EINTR;
+ trans_restart(" (race)");
goto out;
}
@@ -354,10 +357,14 @@ static inline int do_btree_insert_at(struct btree_insert *trans,
}
}
- if (journal_seq_verify(c) &&
- !(trans->flags & BTREE_INSERT_JOURNAL_REPLAY))
- trans_for_each_entry(trans, i)
- i->k->k.version.lo = trans->journal_res.seq;
+ if (!(trans->flags & BTREE_INSERT_JOURNAL_REPLAY)) {
+ if (journal_seq_verify(c))
+ trans_for_each_entry(trans, i)
+ i->k->k.version.lo = trans->journal_res.seq;
+ else if (inject_invalid_keys(c))
+ trans_for_each_entry(trans, i)
+ i->k->k.version = MAX_VERSION;
+ }
trans_for_each_entry(trans, i) {
switch (btree_insert_key_leaf(trans, i)) {
@@ -398,6 +405,17 @@ out:
return ret;
}
+static inline void btree_insert_entry_checks(struct bch_fs *c,
+ struct btree_insert_entry *i)
+{
+ BUG_ON(i->iter->level);
+ BUG_ON(bkey_cmp(bkey_start_pos(&i->k->k), i->iter->pos));
+ BUG_ON(debug_check_bkeys(c) &&
+ !bkey_deleted(&i->k->k) &&
+ bch2_bkey_invalid(c, i->iter->btree_id,
+ bkey_i_to_s_c(i->k)));
+}
+
/**
* __bch_btree_insert_at - insert keys at given iterator positions
*
@@ -418,20 +436,16 @@ int __bch2_btree_insert_at(struct btree_insert *trans)
unsigned flags;
int ret;
+ BUG_ON(!trans->nr);
+
for_each_btree_iter(trans->entries[0].iter, linked)
bch2_btree_iter_verify_locks(linked);
/* for the sake of sanity: */
BUG_ON(trans->nr > 1 && !(trans->flags & BTREE_INSERT_ATOMIC));
- trans_for_each_entry(trans, i) {
- BUG_ON(i->iter->level);
- BUG_ON(bkey_cmp(bkey_start_pos(&i->k->k), i->iter->pos));
- BUG_ON(debug_check_bkeys(c) &&
- !bkey_deleted(&i->k->k) &&
- bch2_bkey_invalid(c, i->iter->btree_id,
- bkey_i_to_s_c(i->k)));
- }
+ trans_for_each_entry(trans, i)
+ btree_insert_entry_checks(c, i);
bubble_sort(trans->entries, trans->nr, btree_trans_cmp);
@@ -442,7 +456,12 @@ retry:
cycle_gc_lock = false;
trans_for_each_entry(trans, i) {
+ unsigned old_locks_want = i->iter->locks_want;
+ unsigned old_uptodate = i->iter->uptodate;
+
if (!bch2_btree_iter_upgrade(i->iter, 1, true)) {
+ trans_restart(" (failed upgrade, locks_want %u uptodate %u)",
+ old_locks_want, old_uptodate);
ret = -EINTR;
goto err;
}
@@ -515,8 +534,10 @@ err:
* don't care if we got ENOSPC because we told split it
* couldn't block:
*/
- if (!ret || (flags & BTREE_INSERT_NOUNLOCK))
+ if (!ret || (flags & BTREE_INSERT_NOUNLOCK)) {
+ trans_restart(" (split)");
ret = -EINTR;
+ }
}
if (cycle_gc_lock) {
@@ -531,13 +552,16 @@ err:
}
if (ret == -EINTR) {
- if (flags & BTREE_INSERT_NOUNLOCK)
+ if (flags & BTREE_INSERT_NOUNLOCK) {
+ trans_restart(" (can't unlock)");
goto out;
+ }
trans_for_each_entry(trans, i) {
int ret2 = bch2_btree_iter_traverse(i->iter);
if (ret2) {
ret = ret2;
+ trans_restart(" (traverse)");
goto out;
}
@@ -550,11 +574,56 @@ err:
*/
if (!(flags & BTREE_INSERT_ATOMIC))
goto retry;
+
+ trans_restart(" (atomic)");
}
goto out;
}
+void bch2_trans_update(struct btree_trans *trans,
+ struct btree_iter *iter,
+ struct bkey_i *k,
+ unsigned extra_journal_res)
+{
+ struct btree_insert_entry *i;
+
+ BUG_ON(trans->nr_updates >= ARRAY_SIZE(trans->updates));
+
+ i = &trans->updates[trans->nr_updates++];
+
+ *i = (struct btree_insert_entry) {
+ .iter = iter,
+ .k = k,
+ .extra_res = extra_journal_res,
+ };
+
+ btree_insert_entry_checks(trans->c, i);
+}
+
+int bch2_trans_commit(struct btree_trans *trans,
+ struct disk_reservation *disk_res,
+ struct extent_insert_hook *hook,
+ u64 *journal_seq,
+ unsigned flags)
+{
+ struct btree_insert insert = {
+ .c = trans->c,
+ .disk_res = disk_res,
+ .journal_seq = journal_seq,
+ .flags = flags,
+ .nr = trans->nr_updates,
+ .entries = trans->updates,
+ };
+
+ if (!trans->nr_updates)
+ return 0;
+
+ trans->nr_updates = 0;
+
+ return __bch2_btree_insert_at(&insert);
+}
+
int bch2_btree_delete_at(struct btree_iter *iter, unsigned flags)
{
struct bkey_i k;