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.c64
1 files changed, 36 insertions, 28 deletions
diff --git a/libbcachefs/btree_update_leaf.c b/libbcachefs/btree_update_leaf.c
index b166ab4b..3a683820 100644
--- a/libbcachefs/btree_update_leaf.c
+++ b/libbcachefs/btree_update_leaf.c
@@ -339,7 +339,7 @@ btree_key_can_insert_cached(struct btree_trans *trans,
{
struct bch_fs *c = trans->c;
struct bkey_cached *ck = (void *) path->l[0].b;
- unsigned old_u64s = ck->u64s, new_u64s;
+ unsigned new_u64s;
struct bkey_i *new_k;
EBUG_ON(path->level);
@@ -368,12 +368,7 @@ btree_key_can_insert_cached(struct btree_trans *trans,
ck->u64s = new_u64s;
ck->k = new_k;
- /*
- * Keys returned by peek() are no longer valid pointers, so we need a
- * transaction restart:
- */
- trace_and_count(c, trans_restart_key_cache_key_realloced, trans, _RET_IP_, path, old_u64s, new_u64s);
- return btree_trans_restart_nounlock(trans, BCH_ERR_transaction_restart_key_cache_realloced);
+ return 0;
}
/* Triggers: */
@@ -1388,11 +1383,41 @@ static int need_whiteout_for_snapshot(struct btree_trans *trans,
static int __must_check
bch2_trans_update_by_path_trace(struct btree_trans *trans, struct btree_path *path,
struct bkey_i *k, enum btree_update_flags flags,
+ unsigned long ip);
+
+static noinline int flush_new_cached_update(struct btree_trans *trans,
+ struct btree_path *path,
+ struct btree_insert_entry *i,
+ enum btree_update_flags flags,
+ unsigned long ip)
+{
+ struct btree_path *btree_path;
+ int ret;
+
+ i->key_cache_already_flushed = true;
+ i->flags |= BTREE_TRIGGER_NORUN;
+
+ btree_path = bch2_path_get(trans, path->btree_id, path->pos, 1, 0,
+ BTREE_ITER_INTENT, _THIS_IP_);
+
+ ret = bch2_btree_path_traverse(trans, btree_path, 0);
+ if (ret)
+ goto err;
+
+ btree_path_set_should_be_locked(btree_path);
+ ret = bch2_trans_update_by_path_trace(trans, btree_path, i->k, flags, ip);
+err:
+ bch2_path_put(trans, btree_path, true);
+ return ret;
+}
+
+static int __must_check
+bch2_trans_update_by_path_trace(struct btree_trans *trans, struct btree_path *path,
+ struct bkey_i *k, enum btree_update_flags flags,
unsigned long ip)
{
struct bch_fs *c = trans->c;
struct btree_insert_entry *i, n;
- int ret = 0;
BUG_ON(!path->should_be_locked);
@@ -1461,27 +1486,10 @@ bch2_trans_update_by_path_trace(struct btree_trans *trans, struct btree_path *pa
* the key cache - but the key has to exist in the btree for that to
* work:
*/
- if (path->cached &&
- bkey_deleted(&i->old_k)) {
- struct btree_path *btree_path;
-
- i->key_cache_already_flushed = true;
- i->flags |= BTREE_TRIGGER_NORUN;
+ if (unlikely(path->cached && bkey_deleted(&i->old_k)))
+ return flush_new_cached_update(trans, path, i, flags, ip);
- btree_path = bch2_path_get(trans, path->btree_id, path->pos, 1, 0,
- BTREE_ITER_INTENT, _THIS_IP_);
-
- ret = bch2_btree_path_traverse(trans, btree_path, 0);
- if (ret)
- goto err;
-
- btree_path_set_should_be_locked(btree_path);
- ret = bch2_trans_update_by_path_trace(trans, btree_path, k, flags, ip);
-err:
- bch2_path_put(trans, btree_path, true);
- }
-
- return ret;
+ return 0;
}
static int __must_check