bcachefs: Add a mempool for btree_trans bump allocator
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 24 Apr 2021 04:09:06 +0000 (00:09 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:54 +0000 (17:08 -0400)
This allocation is required for filesystem operations to make forward
progress, thus needs a mempool.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bcachefs.h
fs/bcachefs/btree_iter.c
fs/bcachefs/btree_types.h

index 9502f393a59ff6ea42e0990910241c1ee91b10b0..8c279261c98c20ad5bfd906262242be6fe18fb98 100644 (file)
@@ -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;
index 660e9e827ed42f3e6e249c7916ce4050c3d0bf88..96814a2447842f90c314875b5860acc64130f01f 100644 (file)
@@ -2181,7 +2181,16 @@ static int bch2_trans_preload_mem(struct btree_trans *trans, size_t size)
        if (size > trans->mem_bytes) {
                size_t old_bytes = trans->mem_bytes;
                size_t new_bytes = roundup_pow_of_two(size);
-               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 -ENOMEM;
@@ -2293,8 +2302,13 @@ void bch2_trans_init(struct btree_trans *trans, struct bch_fs *c,
        if (expected_mem_bytes) {
                expected_mem_bytes = roundup_pow_of_two(expected_mem_bytes);
                trans->mem = kmalloc(expected_mem_bytes, GFP_KERNEL);
-               if (trans->mem)
+
+               if (!unlikely(trans->mem)) {
+                       trans->mem = mempool_alloc(&c->btree_trans_mem_pool, GFP_KERNEL);
+                       trans->mem_bytes = BTREE_TRANS_MEM_MAX;
+               } else {
                        trans->mem_bytes = expected_mem_bytes;
+               }
        }
 
        trans->srcu_idx = srcu_read_lock(&c->btree_trans_barrier);
@@ -2324,7 +2338,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__
        /*
@@ -2332,6 +2350,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);
 
@@ -2407,6 +2426,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);
 }
@@ -2422,5 +2442,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);
 }
index 55d8d815a04ad2d95034c9f581541273485924fe..38414d19e71e7802f132bcc71f1dd069ec56f31b 100644 (file)
@@ -346,6 +346,8 @@ struct btree_insert_entry {
 #define BTREE_ITER_MAX         32
 #endif
 
+#define BTREE_TRANS_MEM_MAX    (1U << 14)
+
 struct btree_trans {
        struct bch_fs           *c;
 #ifdef CONFIG_BCACHEFS_DEBUG