diff options
Diffstat (limited to 'libbcachefs/btree_update_leaf.c')
-rw-r--r-- | libbcachefs/btree_update_leaf.c | 64 |
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 |