summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-04-24 00:09:06 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2021-04-24 12:10:12 -0400
commit6a66e14c2844c7d0fb0c8879b03cb75a2c1ae2c1 (patch)
tree2af263bf864e2c1dbac19f6a28d00f91a6010acb
parent9733cb7cdda22611410045b2f40072cebcf2eebe (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.h1
-rw-r--r--fs/bcachefs/btree_iter.c28
-rw-r--r--fs/bcachefs/btree_types.h2
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