bcachefs: Progress indicator for extents_to_backpointers
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 28 Aug 2024 00:21:03 +0000 (20:21 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Sep 2024 15:39:48 +0000 (11:39 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/backpointers.c

index d4da6343efa9bd028a9aca93223b6d261105a9fd..2bdce3185f2977bba01e8e8a73d49546de81c83f 100644 (file)
@@ -3,12 +3,14 @@
 #include "bbpos.h"
 #include "alloc_background.h"
 #include "backpointers.h"
+#include "bbpos.h"
 #include "bkey_buf.h"
 #include "btree_cache.h"
 #include "btree_update.h"
 #include "btree_update_interior.h"
 #include "btree_write_buffer.h"
 #include "checksum.h"
+#include "disk_accounting.h"
 #include "error.h"
 
 #include <linux/mm.h>
@@ -782,12 +784,80 @@ static int bch2_get_btree_in_memory_pos(struct btree_trans *trans,
        return ret;
 }
 
+struct progress_indicator_state {
+       unsigned long           next_print;
+       u64                     nodes_seen;
+       u64                     nodes_total;
+       struct btree            *last_node;
+};
+
+static inline void progress_init(struct progress_indicator_state *s,
+                                struct bch_fs *c,
+                                u64 btree_id_mask)
+{
+       memset(s, 0, sizeof(*s));
+
+       s->next_print = jiffies + HZ * 10;
+
+       for (unsigned i = 0; i < BTREE_ID_NR; i++) {
+               if (!(btree_id_mask & BIT_ULL(i)))
+                       continue;
+
+               struct disk_accounting_pos acc = {
+                       .type           = BCH_DISK_ACCOUNTING_btree,
+                       .btree.id       = i,
+               };
+
+               u64 v;
+               bch2_accounting_mem_read(c, disk_accounting_pos_to_bpos(&acc), &v, 1);
+               s->nodes_total += div64_ul(v, btree_sectors(c));
+       }
+}
+
+static inline bool progress_update_p(struct progress_indicator_state *s)
+{
+       bool ret = time_after_eq(jiffies, s->next_print);
+
+       if (ret)
+               s->next_print = jiffies + HZ * 10;
+       return ret;
+}
+
+static void progress_update_iter(struct btree_trans *trans,
+                                struct progress_indicator_state *s,
+                                struct btree_iter *iter,
+                                const char *msg)
+{
+       struct bch_fs *c = trans->c;
+       struct btree *b = path_l(btree_iter_path(trans, iter))->b;
+
+       s->nodes_seen += b != s->last_node;
+       s->last_node = b;
+
+       if (progress_update_p(s)) {
+               struct printbuf buf = PRINTBUF;
+               unsigned percent = s->nodes_total
+                       ? div64_u64(s->nodes_seen * 100, s->nodes_total)
+                       : 0;
+
+               prt_printf(&buf, "%s: %d%%, done %llu/%llu nodes, at ",
+                          msg, percent, s->nodes_seen, s->nodes_total);
+               bch2_bbpos_to_text(&buf, BBPOS(iter->btree_id, iter->pos));
+
+               bch_info(c, "%s", buf.buf);
+               printbuf_exit(&buf);
+       }
+}
+
 static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
                                                   struct extents_to_bp_state *s)
 {
        struct bch_fs *c = trans->c;
+       struct progress_indicator_state progress;
        int ret = 0;
 
+       progress_init(&progress, trans->c, BIT_ULL(BTREE_ID_extents)|BIT_ULL(BTREE_ID_reflink));
+
        for (enum btree_id btree_id = 0;
             btree_id < btree_id_nr_alive(c);
             btree_id++) {
@@ -805,6 +875,7 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
                                                  BTREE_ITER_prefetch);
 
                        ret = for_each_btree_key_continue(trans, iter, 0, k, ({
+                               progress_update_iter(trans, &progress, &iter, "extents_to_backpointers");
                                check_extent_to_backpointers(trans, s, btree_id, level, k) ?:
                                bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
                        }));
@@ -920,19 +991,24 @@ static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans,
                                                   struct bbpos start,
                                                   struct bbpos end)
 {
+       struct bch_fs *c = trans->c;
        struct bkey_buf last_flushed;
+       struct progress_indicator_state progress;
 
        bch2_bkey_buf_init(&last_flushed);
        bkey_init(&last_flushed.k->k);
+       progress_init(&progress, trans->c, BIT_ULL(BTREE_ID_backpointers));
 
        int ret = for_each_btree_key_commit(trans, iter, BTREE_ID_backpointers,
                                  POS_MIN, BTREE_ITER_prefetch, k,
-                                 NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
-               check_one_backpointer(trans, start, end,
-                                     bkey_s_c_to_backpointer(k),
-                                     &last_flushed));
-
-       bch2_bkey_buf_exit(&last_flushed, trans->c);
+                                 NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
+                       progress_update_iter(trans, &progress, &iter, "backpointers_to_extents");
+                       check_one_backpointer(trans, start, end,
+                                             bkey_s_c_to_backpointer(k),
+                                             &last_flushed);
+       }));
+
+       bch2_bkey_buf_exit(&last_flushed, c);
        return ret;
 }