bcachefs: Track maximum transaction memory
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 23 Aug 2022 01:49:55 +0000 (21:49 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:39 +0000 (17:09 -0400)
This patch
 - tracks maximum bch2_trans_kmalloc() memory used in btree_transaction_stats
 - makes it available in debugfs
 - switches bch2_trans_init() to using that for the amount of memory to
   preallocate, instead of the parameter passed in

This drastically reduces transaction restarts, and means we no longer
need to track this in the source code.

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

index f8b7434534ebf9cca67b6f2733f1ec5c892c242d..9e6c10dfa443f457ffcc86e244b3196b7fe063b0 100644 (file)
@@ -533,6 +533,7 @@ struct btree_transaction_stats {
        struct bch2_time_stats  lock_hold_times;
        struct mutex            lock;
        unsigned                nr_max_paths;
+       unsigned                max_mem;
        char                    *max_paths_text;
 };
 
index 1dc243f63b2d1a9ca08c36270c2b26cb12941f37..f62f75ff82b22d6da4a21c78845f6f180e06dbd7 100644 (file)
@@ -2747,9 +2747,11 @@ void bch2_trans_copy_iter(struct btree_iter *dst, struct btree_iter *src)
 
 void *bch2_trans_kmalloc(struct btree_trans *trans, size_t size)
 {
-       size_t new_top = trans->mem_top + size;
+       unsigned new_top = trans->mem_top + size;
        void *p;
 
+       trans->mem_max = max(trans->mem_max, new_top);
+
        if (new_top > trans->mem_bytes) {
                size_t old_bytes = trans->mem_bytes;
                size_t new_bytes = roundup_pow_of_two(new_top);
@@ -2887,10 +2889,7 @@ static inline unsigned bch2_trans_get_fn_idx(struct btree_trans *trans, struct b
        return i;
 }
 
-void __bch2_trans_init(struct btree_trans *trans, struct bch_fs *c,
-                      unsigned expected_nr_iters,
-                      size_t expected_mem_bytes,
-                      const char *fn)
+void __bch2_trans_init(struct btree_trans *trans, struct bch_fs *c, const char *fn)
        __acquires(&c->btree_trans_barrier)
 {
        struct btree_transaction_stats *s;
@@ -2906,8 +2905,10 @@ void __bch2_trans_init(struct btree_trans *trans, struct bch_fs *c,
 
        bch2_trans_alloc_paths(trans, c);
 
-       if (expected_mem_bytes) {
-               expected_mem_bytes = roundup_pow_of_two(expected_mem_bytes);
+       s = btree_trans_stats(trans);
+       if (s) {
+               unsigned expected_mem_bytes = roundup_pow_of_two(s->max_mem);
+
                trans->mem = kmalloc(expected_mem_bytes, GFP_KERNEL);
 
                if (!unlikely(trans->mem)) {
@@ -2916,11 +2917,9 @@ void __bch2_trans_init(struct btree_trans *trans, struct bch_fs *c,
                } else {
                        trans->mem_bytes = expected_mem_bytes;
                }
-       }
 
-       s = btree_trans_stats(trans);
-       if (s)
                trans->nr_max_paths = s->nr_max_paths;
+       }
 
        trans->srcu_idx = srcu_read_lock(&c->btree_trans_barrier);
 
@@ -2967,9 +2966,13 @@ void bch2_trans_exit(struct btree_trans *trans)
 {
        struct btree_insert_entry *i;
        struct bch_fs *c = trans->c;
+       struct btree_transaction_stats *s = btree_trans_stats(trans);
 
        bch2_trans_unlock(trans);
 
+       if (s)
+               s->max_mem = max(s->max_mem, trans->mem_max);
+
        trans_for_each_update(trans, i)
                __btree_path_put(i->path, true);
        trans->nr_updates               = 0;
index c083e49475d10dffd2bc8bc9cd602248d3416c0e..87b456998ef44a32296446c49c5bf997b6721957 100644 (file)
@@ -564,11 +564,10 @@ void bch2_btree_path_to_text(struct printbuf *, struct btree_path *);
 void bch2_trans_paths_to_text(struct printbuf *, struct btree_trans *);
 void bch2_dump_trans_updates(struct btree_trans *);
 void bch2_dump_trans_paths_updates(struct btree_trans *);
-void __bch2_trans_init(struct btree_trans *, struct bch_fs *,
-                      unsigned, size_t, const char *);
+void __bch2_trans_init(struct btree_trans *, struct bch_fs *, const char *);
 void bch2_trans_exit(struct btree_trans *);
 
-#define bch2_trans_init(...)   __bch2_trans_init(__VA_ARGS__, __func__)
+#define bch2_trans_init(_trans, _c, _nr_iters, _mem) __bch2_trans_init(_trans, _c, __func__)
 
 void bch2_btree_trans_to_text(struct printbuf *, struct btree_trans *);
 
index ce148c21fd3be7c5b4c0d6b4c2314d048a521c11..42459a5bf035d5158b0daace975f94ccda01a8db 100644 (file)
@@ -420,6 +420,7 @@ struct btree_trans {
        u64                     paths_allocated;
 
        unsigned                mem_top;
+       unsigned                mem_max;
        unsigned                mem_bytes;
        void                    *mem;
 
index 86c4b023ac7cf6f2c6f11a1a6094107ecf6a18c5..4fe20d36212e4aa968810849a07a9af63f3b43c5 100644 (file)
@@ -667,6 +667,9 @@ static ssize_t lock_held_stats_read(struct file *file, char __user *buf,
 
                mutex_lock(&s->lock);
 
+               prt_printf(&i->buf, "Max mem used: %u", s->max_mem);
+               prt_newline(&i->buf);
+
                if (IS_ENABLED(CONFIG_BCACHEFS_LOCK_TIME_STATS)) {
                        prt_printf(&i->buf, "Lock hold times:");
                        prt_newline(&i->buf);