Skip to content

Commit 09b0283

Browse files
author
Kent Overstreet
committed
bcachefs: Make sure to drop/retake btree locks before reclaim
We really don't want to be invoking memory reclaim with btree locks held: even aside from (solvable, but tricky) recursion issues, it can cause painful to diagnose performance edge cases. This fixes a recently reported issue in btree_key_can_insert_cached(). Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev> Reported-by: Mateusz Guzik <mjguzik@gmail.com> Fixes: https://lore.kernel.org/linux-bcachefs/CAGudoHEsb_hGRMeWeXh+UF6po0qQuuq_NKSEo+s1sEb6bDLjpA@mail.gmail.com/T/
1 parent 3b8c450 commit 09b0283

1 file changed

Lines changed: 42 additions & 6 deletions

File tree

fs/bcachefs/btree_trans_commit.c

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,45 @@ static inline int btree_key_can_insert(struct btree_trans *trans,
368368
return 0;
369369
}
370370

371+
noinline static int
372+
btree_key_can_insert_cached_slowpath(struct btree_trans *trans, unsigned flags,
373+
struct btree_path *path, unsigned new_u64s)
374+
{
375+
struct bch_fs *c = trans->c;
376+
struct btree_insert_entry *i;
377+
struct bkey_cached *ck = (void *) path->l[0].b;
378+
struct bkey_i *new_k;
379+
int ret;
380+
381+
bch2_trans_unlock_write(trans);
382+
bch2_trans_unlock(trans);
383+
384+
new_k = kmalloc(new_u64s * sizeof(u64), GFP_KERNEL);
385+
if (!new_k) {
386+
bch_err(c, "error allocating memory for key cache key, btree %s u64s %u",
387+
bch2_btree_id_str(path->btree_id), new_u64s);
388+
return -BCH_ERR_ENOMEM_btree_key_cache_insert;
389+
}
390+
391+
ret = bch2_trans_relock(trans) ?:
392+
bch2_trans_lock_write(trans);
393+
if (unlikely(ret)) {
394+
kfree(new_k);
395+
return ret;
396+
}
397+
398+
memcpy(new_k, ck->k, ck->u64s * sizeof(u64));
399+
400+
trans_for_each_update(trans, i)
401+
if (i->old_v == &ck->k->v)
402+
i->old_v = &new_k->v;
403+
404+
kfree(ck->k);
405+
ck->u64s = new_u64s;
406+
ck->k = new_k;
407+
return 0;
408+
}
409+
371410
static int btree_key_can_insert_cached(struct btree_trans *trans, unsigned flags,
372411
struct btree_path *path, unsigned u64s)
373412
{
@@ -394,12 +433,9 @@ static int btree_key_can_insert_cached(struct btree_trans *trans, unsigned flags
394433
return 0;
395434

396435
new_u64s = roundup_pow_of_two(u64s);
397-
new_k = krealloc(ck->k, new_u64s * sizeof(u64), GFP_NOFS);
398-
if (!new_k) {
399-
bch_err(c, "error allocating memory for key cache key, btree %s u64s %u",
400-
bch2_btree_id_str(path->btree_id), new_u64s);
401-
return -BCH_ERR_ENOMEM_btree_key_cache_insert;
402-
}
436+
new_k = krealloc(ck->k, new_u64s * sizeof(u64), GFP_NOWAIT);
437+
if (unlikely(!new_k))
438+
return btree_key_can_insert_cached_slowpath(trans, flags, path, new_u64s);
403439

404440
trans_for_each_update(trans, i)
405441
if (i->old_v == &ck->k->v)

0 commit comments

Comments
 (0)