diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-04-24 00:09:06 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2021-04-24 12:10:12 -0400 |
commit | 6a66e14c2844c7d0fb0c8879b03cb75a2c1ae2c1 (patch) | |
tree | 2af263bf864e2c1dbac19f6a28d00f91a6010acb | |
parent | 9733cb7cdda22611410045b2f40072cebcf2eebe (diff) |
bcachefs: Add a mempool for btree_trans bump allocator
This allocation is required for filesystem operations to make forward
progress, thus needs a mempool.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/bcachefs.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/btree_iter.c | 28 | ||||
-rw-r--r-- | fs/bcachefs/btree_types.h | 2 |
3 files changed, 28 insertions, 3 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index ebc941d9439c..949139670eec 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -644,6 +644,7 @@ struct bch_fs { struct mutex btree_trans_lock; struct list_head btree_trans_list; mempool_t btree_iters_pool; + mempool_t btree_trans_mem_pool; struct btree_iter_buf __percpu *btree_iters_bufs; struct srcu_struct btree_trans_barrier; diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index c8f527bc2ea2..975b87a356a8 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -2145,7 +2145,16 @@ void *bch2_trans_kmalloc(struct btree_trans *trans, size_t size) if (new_top > trans->mem_bytes) { size_t old_bytes = trans->mem_bytes; size_t new_bytes = roundup_pow_of_two(new_top); - void *new_mem = krealloc(trans->mem, new_bytes, GFP_NOFS); + void *new_mem; + + 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); + } if (!new_mem) return ERR_PTR(-ENOMEM); @@ -2249,6 +2258,11 @@ void bch2_trans_init(struct btree_trans *trans, struct bch_fs *c, if (expected_mem_bytes) { trans->mem_bytes = roundup_pow_of_two(expected_mem_bytes); trans->mem = kmalloc(trans->mem_bytes, GFP_KERNEL|__GFP_NOFAIL); + + if (!unlikely(trans->mem)) { + trans->mem = mempool_alloc(&c->btree_trans_mem_pool, GFP_KERNEL); + trans->mem_bytes = BTREE_TRANS_MEM_MAX; + } } trans->srcu_idx = srcu_read_lock(&c->btree_trans_barrier); @@ -2291,7 +2305,11 @@ int bch2_trans_exit(struct btree_trans *trans) bch2_journal_preres_put(&trans->c->journal, &trans->journal_preres); kfree(trans->fs_usage_deltas); - kfree(trans->mem); + + if (trans->mem_bytes == BTREE_TRANS_MEM_MAX) + mempool_free(trans->mem, &trans->c->btree_trans_mem_pool); + else + kfree(trans->mem); #ifdef __KERNEL__ /* @@ -2299,6 +2317,7 @@ int bch2_trans_exit(struct btree_trans *trans) */ trans->iters = this_cpu_xchg(c->btree_iters_bufs->iter, trans->iters); #endif + if (trans->iters) mempool_free(trans->iters, &trans->c->btree_iters_pool); @@ -2392,6 +2411,7 @@ void bch2_btree_trans_to_text(struct printbuf *out, struct bch_fs *c) void bch2_fs_btree_iter_exit(struct bch_fs *c) { + mempool_exit(&c->btree_trans_mem_pool); mempool_exit(&c->btree_iters_pool); cleanup_srcu_struct(&c->btree_trans_barrier); } @@ -2407,5 +2427,7 @@ int bch2_fs_btree_iter_init(struct bch_fs *c) mempool_init_kmalloc_pool(&c->btree_iters_pool, 1, sizeof(struct btree_iter) * nr + sizeof(struct btree_insert_entry) * nr + - sizeof(struct btree_insert_entry) * nr); + sizeof(struct btree_insert_entry) * nr) ?: + mempool_init_kmalloc_pool(&c->btree_trans_mem_pool, 1, + BTREE_TRANS_MEM_MAX); } diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index f942ccf62ff4..06a2c412db7a 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -352,6 +352,8 @@ struct btree_trans_commit_hook { struct btree_trans_commit_hook *next; }; +#define BTREE_TRANS_MEM_MAX 4096 + struct btree_trans { struct bch_fs *c; #ifdef CONFIG_BCACHEFS_DEBUG |