bcachefs: Add a mempool for the replicas delta list
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 24 Apr 2021 04:24:25 +0000 (00:24 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:54 +0000 (17:08 -0400)
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/buckets.c
fs/bcachefs/replicas.c
fs/bcachefs/replicas.h
fs/bcachefs/super.c

index 8c279261c98c20ad5bfd906262242be6fe18fb98..51ba38f19ca9c102a11b7212a3c1318e92520c2e 100644 (file)
@@ -546,6 +546,8 @@ struct btree_iter_buf {
        struct btree_iter       *iter;
 };
 
+#define REPLICAS_DELTA_LIST_MAX        (1U << 16)
+
 struct bch_fs {
        struct closure          cl;
 
@@ -573,6 +575,7 @@ struct bch_fs {
        struct bch_replicas_cpu replicas;
        struct bch_replicas_cpu replicas_gc;
        struct mutex            replicas_gc_lock;
+       mempool_t               replicas_delta_pool;
 
        struct journal_entry_res btree_root_journal_res;
        struct journal_entry_res replicas_journal_res;
index 96814a2447842f90c314875b5860acc64130f01f..eccc9bb0e4e9c827c405d8f5dbb6f8c1d6d1354f 100644 (file)
@@ -2337,7 +2337,14 @@ int bch2_trans_exit(struct btree_trans *trans)
 
        bch2_journal_preres_put(&trans->c->journal, &trans->journal_preres);
 
-       kfree(trans->fs_usage_deltas);
+       if (trans->fs_usage_deltas) {
+               if (trans->fs_usage_deltas->size + sizeof(trans->fs_usage_deltas) ==
+                   REPLICAS_DELTA_LIST_MAX)
+                       mempool_free(trans->fs_usage_deltas,
+                                    &trans->c->replicas_delta_pool);
+               else
+                       kfree(trans->fs_usage_deltas);
+       }
 
        if (trans->mem_bytes == BTREE_TRANS_MEM_MAX)
                mempool_free(trans->mem, &trans->c->btree_trans_mem_pool);
index 66e50e6b36eaecececcbf7f3b31ba777cb9dd7f0..3dcc77d5242f723b5cadd5d902b6fe925f589daf 100644 (file)
@@ -560,10 +560,26 @@ replicas_deltas_realloc(struct btree_trans *trans, unsigned more)
 {
        struct replicas_delta_list *d = trans->fs_usage_deltas;
        unsigned new_size = d ? (d->size + more) * 2 : 128;
+       unsigned alloc_size = sizeof(*d) + new_size;
+
+       WARN_ON_ONCE(alloc_size > REPLICAS_DELTA_LIST_MAX);
 
        if (!d || d->used + more > d->size) {
-               d = krealloc(d, sizeof(*d) + new_size, GFP_NOIO|__GFP_ZERO);
-               BUG_ON(!d);
+               d = krealloc(d, alloc_size, GFP_NOIO|__GFP_ZERO);
+
+               BUG_ON(!d && alloc_size > REPLICAS_DELTA_LIST_MAX);
+
+               if (!d) {
+                       d = mempool_alloc(&trans->c->replicas_delta_pool, GFP_NOIO);
+                       memset(d, 0, REPLICAS_DELTA_LIST_MAX);
+
+                       if (trans->fs_usage_deltas)
+                               memcpy(d, trans->fs_usage_deltas,
+                                      trans->fs_usage_deltas->size + sizeof(*d));
+
+                       new_size = REPLICAS_DELTA_LIST_MAX - sizeof(*d);
+                       kfree(trans->fs_usage_deltas);
+               }
 
                d->size = new_size;
                trans->fs_usage_deltas = d;
index 15ff0d3c936a57df2d0aec97095fb496f12cf8ac..ddaf833d0bf28d3686a73d87463895c042adf58b 100644 (file)
@@ -1033,11 +1033,27 @@ unsigned bch2_dev_has_data(struct bch_fs *c, struct bch_dev *ca)
        return ret;
 }
 
+void bch2_fs_replicas_exit(struct bch_fs *c)
+{
+       unsigned i;
+
+       kfree(c->usage_scratch);
+       for (i = 0; i < ARRAY_SIZE(c->usage); i++)
+               free_percpu(c->usage[i]);
+       kfree(c->usage_base);
+       kfree(c->replicas.entries);
+       kfree(c->replicas_gc.entries);
+
+       mempool_exit(&c->replicas_delta_pool);
+}
+
 int bch2_fs_replicas_init(struct bch_fs *c)
 {
        bch2_journal_entry_res_resize(&c->journal,
                        &c->replicas_journal_res,
                        reserve_journal_replicas(c, &c->replicas));
 
-       return replicas_table_update(c, &c->replicas);
+       return mempool_init_kmalloc_pool(&c->replicas_delta_pool, 1,
+                                        REPLICAS_DELTA_LIST_MAX) ?:
+               replicas_table_update(c, &c->replicas);
 }
index 9c8fd3d9824767448f3dcdfe321ff4fd2be1f523..8cb1f592f1b62892adf8141b08c86b6c30d7fb36 100644 (file)
@@ -77,6 +77,7 @@ int bch2_sb_replicas_to_cpu_replicas(struct bch_fs *);
 extern const struct bch_sb_field_ops bch_sb_field_ops_replicas;
 extern const struct bch_sb_field_ops bch_sb_field_ops_replicas_v0;
 
+void bch2_fs_replicas_exit(struct bch_fs *);
 int bch2_fs_replicas_init(struct bch_fs *);
 
 #endif /* _BCACHEFS_REPLICAS_H */
index 8de04bfae800acf9c922ecd663b6924581df61f1..be6e66e0db714c91675cf0d7fbcfa37db5bb3e66 100644 (file)
@@ -476,6 +476,7 @@ static void __bch2_fs_free(struct bch_fs *c)
        bch2_fs_btree_iter_exit(c);
        bch2_fs_btree_key_cache_exit(&c->btree_key_cache);
        bch2_fs_btree_cache_exit(c);
+       bch2_fs_replicas_exit(c);
        bch2_fs_journal_exit(&c->journal);
        bch2_io_clock_exit(&c->io_clock[WRITE]);
        bch2_io_clock_exit(&c->io_clock[READ]);
@@ -484,10 +485,6 @@ static void __bch2_fs_free(struct bch_fs *c)
        bch2_journal_entries_free(&c->journal_entries);
        percpu_free_rwsem(&c->mark_lock);
        free_percpu(c->online_reserved);
-       kfree(c->usage_scratch);
-       for (i = 0; i < ARRAY_SIZE(c->usage); i++)
-               free_percpu(c->usage[i]);
-       kfree(c->usage_base);
 
        if (c->btree_iters_bufs)
                for_each_possible_cpu(cpu)
@@ -500,8 +497,6 @@ static void __bch2_fs_free(struct bch_fs *c)
        bioset_exit(&c->btree_bio);
        mempool_exit(&c->fill_iter);
        percpu_ref_exit(&c->writes);
-       kfree(c->replicas.entries);
-       kfree(c->replicas_gc.entries);
        kfree(rcu_dereference_protected(c->disk_groups, 1));
        kfree(c->journal_seq_blacklist_table);
        kfree(c->unused_inode_hints);