diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-04-24 07:24:25 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:08:54 +0300 |
commit | 9620c3ec2fa83e18f52e99b3dd2e8451446ca17e (patch) | |
tree | 6923afc85e76ef5f67b046b70f39bb46cc51d8b7 /fs | |
parent | e131b6aa0a316f9724e6e8ad2f9be091c07115a7 (diff) | |
download | linux-9620c3ec2fa83e18f52e99b3dd2e8451446ca17e.tar.xz |
bcachefs: Add a mempool for the replicas delta list
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/bcachefs.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/btree_iter.c | 9 | ||||
-rw-r--r-- | fs/bcachefs/buckets.c | 20 | ||||
-rw-r--r-- | fs/bcachefs/replicas.c | 18 | ||||
-rw-r--r-- | fs/bcachefs/replicas.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 7 |
6 files changed, 48 insertions, 10 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 8c279261c98c..51ba38f19ca9 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -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; diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 96814a244784..eccc9bb0e4e9 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -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); diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index 66e50e6b36ea..3dcc77d5242f 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -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; diff --git a/fs/bcachefs/replicas.c b/fs/bcachefs/replicas.c index 15ff0d3c936a..ddaf833d0bf2 100644 --- a/fs/bcachefs/replicas.c +++ b/fs/bcachefs/replicas.c @@ -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); } diff --git a/fs/bcachefs/replicas.h b/fs/bcachefs/replicas.h index 9c8fd3d98247..8cb1f592f1b6 100644 --- a/fs/bcachefs/replicas.h +++ b/fs/bcachefs/replicas.h @@ -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 */ diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 8de04bfae800..be6e66e0db71 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -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); |