diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-05-28 07:09:50 +0200 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 23:10:03 +0200 |
commit | 78367aaa5af322b64d44a3a3354f4c75c499fef0 (patch) | |
tree | b82ebe61775f333edb4ca8e26273758049081d33 /fs | |
parent | bcachefs: drop_locks_do() (diff) | |
download | linux-78367aaa5af322b64d44a3a3354f4c75c499fef0.tar.xz linux-78367aaa5af322b64d44a3a3354f4c75c499fef0.zip |
bcachefs: bch2_trans_kmalloc no longer allocates memory with btree locks held
When allocating memory, gfp flags should generally be
- GFP_NOWAIT|__GFP_NOWARN if btree locks are held
- GFP_NOFS if in the IO path or otherwise holding resources needed for
IO submission
- GFP_KERNEL otherwise
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/btree_iter.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 1cc53b37f78e..9072819176de 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -2790,6 +2790,7 @@ void *__bch2_trans_kmalloc(struct btree_trans *trans, size_t size) unsigned new_top = trans->mem_top + size; size_t old_bytes = trans->mem_bytes; size_t new_bytes = roundup_pow_of_two(new_top); + int ret; void *new_mem; void *p; @@ -2797,15 +2798,27 @@ void *__bch2_trans_kmalloc(struct btree_trans *trans, size_t size) WARN_ON_ONCE(new_bytes > BTREE_TRANS_MEM_MAX); - new_mem = krealloc(trans->mem, new_bytes, GFP_NOFS); - if (!new_mem && new_bytes <= BTREE_TRANS_MEM_MAX) { - new_mem = mempool_alloc(&trans->c->btree_trans_mem_pool, GFP_KERNEL); - new_bytes = BTREE_TRANS_MEM_MAX; - kfree(trans->mem); - } + new_mem = krealloc(trans->mem, new_bytes, GFP_NOWAIT|__GFP_NOWARN); + if (unlikely(!new_mem)) { + bch2_trans_unlock(trans); + + new_mem = krealloc(trans->mem, new_bytes, GFP_KERNEL); + if (!new_mem && new_bytes <= BTREE_TRANS_MEM_MAX) { + new_mem = mempool_alloc(&trans->c->btree_trans_mem_pool, GFP_KERNEL); + new_bytes = BTREE_TRANS_MEM_MAX; + kfree(trans->mem); + } + + if (!new_mem) + return ERR_PTR(-BCH_ERR_ENOMEM_trans_kmalloc); + + trans->mem = new_mem; + trans->mem_bytes = new_bytes; - if (!new_mem) - return ERR_PTR(-BCH_ERR_ENOMEM_trans_kmalloc); + ret = bch2_trans_relock(trans); + if (ret) + return ERR_PTR(ret); + } trans->mem = new_mem; trans->mem_bytes = new_bytes; |