bcachefs: add progress stats to sysfs
authorBrett Holman <bholman.devel@gmail.com>
Fri, 23 Jul 2021 19:57:19 +0000 (13:57 -0600)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:10 +0000 (17:09 -0400)
This adds progress stats to sysfs for copygc, rebalance, recovery, and the
cmd_job ioctls.

Signed-off-by: Brett Holman <bholman.devel@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bcachefs.h
fs/bcachefs/move.c
fs/bcachefs/move.h
fs/bcachefs/move_types.h
fs/bcachefs/movinggc.c
fs/bcachefs/rebalance.c
fs/bcachefs/rebalance_types.h
fs/bcachefs/recovery.c
fs/bcachefs/super.c
fs/bcachefs/sysfs.c

index 6a289b6f1fb4d491bfc16419295ffe22ca46651f..e2aac1da18ae505340509684f2ae49317526ba53 100644 (file)
@@ -792,6 +792,10 @@ mempool_t          bio_bounce_pages;
        struct write_point      copygc_write_point;
        s64                     copygc_wait;
 
+       /* DATA PROGRESS STATS */
+       struct list_head        data_progress_list;
+       struct mutex            data_progress_lock;
+
        /* STRIPES: */
        GENRADIX(struct stripe) stripes[2];
 
index 9a423a3e4570d83bf22d291df207a6d202a821d6..8d28d8fc5395e467f023605245beae3ea23d95e1 100644 (file)
@@ -686,6 +686,30 @@ out:
        return ret;
 }
 
+inline void bch_move_stats_init(struct bch_move_stats *stats, char *name)
+{
+       memset(stats, 0, sizeof(*stats));
+
+       scnprintf(stats->name, sizeof(stats->name),
+                       "%s", name);
+}
+
+static inline void progress_list_add(struct bch_fs *c,
+                                    struct bch_move_stats *stats)
+{
+       mutex_lock(&c->data_progress_lock);
+       list_add(&stats->list, &c->data_progress_list);
+       mutex_unlock(&c->data_progress_lock);
+}
+
+static inline void progress_list_del(struct bch_fs *c,
+                                    struct bch_move_stats *stats)
+{
+       mutex_lock(&c->data_progress_lock);
+       list_del(&stats->list);
+       mutex_unlock(&c->data_progress_lock);
+}
+
 int bch2_move_data(struct bch_fs *c,
                   enum btree_id start_btree_id, struct bpos start_pos,
                   enum btree_id end_btree_id,   struct bpos end_pos,
@@ -698,6 +722,7 @@ int bch2_move_data(struct bch_fs *c,
        enum btree_id id;
        int ret;
 
+       progress_list_add(c, stats);
        closure_init_stack(&ctxt.cl);
        INIT_LIST_HEAD(&ctxt.reads);
        init_waitqueue_head(&ctxt.wait);
@@ -731,6 +756,7 @@ int bch2_move_data(struct bch_fs *c,
                        atomic64_read(&stats->sectors_moved),
                        atomic64_read(&stats->keys_moved));
 
+       progress_list_del(c, stats);
        return ret;
 }
 
@@ -755,6 +781,7 @@ static int bch2_move_btree(struct bch_fs *c,
        int ret = 0;
 
        bch2_trans_init(&trans, c, 0, 0);
+       progress_list_add(c, stats);
 
        stats->data_type = BCH_DATA_btree;
 
@@ -803,6 +830,7 @@ next:
        if (ret)
                bch_err(c, "error %i in bch2_move_btree", ret);
 
+       progress_list_del(c, stats);
        return ret;
 }
 
@@ -944,6 +972,7 @@ int bch2_data_job(struct bch_fs *c,
 
        switch (op.op) {
        case BCH_DATA_OP_REREPLICATE:
+               bch_move_stats_init(stats, "rereplicate");
                stats->data_type = BCH_DATA_journal;
                ret = bch2_journal_flush_device_pins(&c->journal, -1);
 
@@ -968,6 +997,7 @@ int bch2_data_job(struct bch_fs *c,
                if (op.migrate.dev >= c->sb.nr_devices)
                        return -EINVAL;
 
+               bch_move_stats_init(stats, "migrate");
                stats->data_type = BCH_DATA_journal;
                ret = bch2_journal_flush_device_pins(&c->journal, op.migrate.dev);
 
@@ -985,6 +1015,7 @@ int bch2_data_job(struct bch_fs *c,
                ret = bch2_replicas_gc2(c) ?: ret;
                break;
        case BCH_DATA_OP_REWRITE_OLD_NODES:
+               bch_move_stats_init(stats, "rewrite_old_nodes");
                ret = bch2_scan_old_btree_nodes(c, stats);
                break;
        default:
index 99d6acb108806ae7850463ef35971136b484b058..901d8f8759465468368b7c54b4bd794cb2b9a05c 100644 (file)
@@ -67,4 +67,8 @@ int bch2_data_job(struct bch_fs *,
                  struct bch_move_stats *,
                  struct bch_ioctl_data);
 
+inline void bch_move_stats_init(struct bch_move_stats *stats,
+                               char *name);
+
+
 #endif /* _BCACHEFS_MOVE_H */
index fc0de165af9fe354b246e24ca223904c87e7dc0b..9df6d18137a5e02655d6c34f10730b896f9d48d5 100644 (file)
@@ -6,6 +6,8 @@ struct bch_move_stats {
        enum bch_data_type      data_type;
        enum btree_id           btree_id;
        struct bpos             pos;
+       struct list_head        list;
+       char                    name[32];
 
        atomic64_t              keys_moved;
        atomic64_t              keys_raced;
index 651381a5ccc5f7b3577f7f68468ccf90a90539fe..b05dcbbd1a476272d03ffe1a2690c73175d0f3af 100644 (file)
@@ -147,7 +147,8 @@ static int bch2_copygc(struct bch_fs *c)
        size_t b, heap_size = 0;
        int ret;
 
-       memset(&move_stats, 0, sizeof(move_stats));
+       bch_move_stats_init(&move_stats, "copygc");
+
        /*
         * Find buckets with lowest sector counts, skipping completely
         * empty buckets, by building a maxheap sorted by sector count,
index b7e61da0f4d1cb185e5b4ded3f547f5b82b92323..fe0a1dbac199fd8c70673d5adf59944f51b6c4b6 100644 (file)
@@ -166,6 +166,7 @@ static int bch2_rebalance_thread(void *arg)
        struct bch_fs_rebalance *r = &c->rebalance;
        struct io_clock *clock = &c->io_clock[WRITE];
        struct rebalance_work w, p;
+       struct bch_move_stats move_stats;
        unsigned long start, prev_start;
        unsigned long prev_run_time, prev_run_cputime;
        unsigned long cputime, prev_cputime;
@@ -179,6 +180,7 @@ static int bch2_rebalance_thread(void *arg)
        prev_start      = jiffies;
        prev_cputime    = curr_cputime();
 
+       bch_move_stats_init(&move_stats, "rebalance");
        while (!kthread_wait_freezable(r->enabled)) {
                cond_resched();
 
@@ -235,7 +237,7 @@ static int bch2_rebalance_thread(void *arg)
                prev_cputime    = cputime;
 
                r->state = REBALANCE_RUNNING;
-               memset(&r->move_stats, 0, sizeof(r->move_stats));
+               memset(&move_stats, 0, sizeof(move_stats));
                rebalance_work_reset(c);
 
                bch2_move_data(c,
@@ -245,7 +247,7 @@ static int bch2_rebalance_thread(void *arg)
                               NULL, /*  &r->pd.rate, */
                               writepoint_ptr(&c->rebalance_write_point),
                               rebalance_pred, NULL,
-                              &r->move_stats);
+                              &move_stats);
        }
 
        return 0;
@@ -281,10 +283,7 @@ void bch2_rebalance_work_to_text(struct printbuf *out, struct bch_fs *c)
                       h1);
                break;
        case REBALANCE_RUNNING:
-               pr_buf(out, "running\n"
-                      "pos ");
-               bch2_bpos_to_text(out, r->move_stats.pos);
-               pr_buf(out, "\n");
+               pr_buf(out, "running\n");
                break;
        }
 }
index 2f62a643c39fbb0c08f024fbf58a7f3325755875..7462a92e95985d91cdc454485d045659240dd0fc 100644 (file)
@@ -19,7 +19,6 @@ struct bch_fs_rebalance {
        enum rebalance_state    state;
        u64                     throttled_until_iotime;
        unsigned long           throttled_until_cputime;
-       struct bch_move_stats   move_stats;
 
        unsigned                enabled:1;
 };
index afb72648fe5416a0cba73f59548f1933ad78fc86..b02af94f40370734b346a0119e33b27650da5c00 100644 (file)
@@ -1216,7 +1216,9 @@ use_clean:
 
        if (!(c->sb.compat & (1ULL << BCH_COMPAT_extents_above_btree_updates_done)) ||
            !(c->sb.compat & (1ULL << BCH_COMPAT_bformat_overflow_done))) {
-               struct bch_move_stats stats = { 0 };
+               struct bch_move_stats stats;
+
+               bch_move_stats_init(&stats, "recovery");
 
                bch_info(c, "scanning for old btree nodes");
                ret = bch2_fs_read_write(c);
index 11557a863d3dbbb473d9639ef3e9027eecbcdf9e..1d793e554084533eb072ed8015431ed3cd1511a1 100644 (file)
@@ -712,6 +712,9 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
        INIT_LIST_HEAD(&c->ec_stripe_new_list);
        mutex_init(&c->ec_stripe_new_lock);
 
+       INIT_LIST_HEAD(&c->data_progress_list);
+       mutex_init(&c->data_progress_lock);
+
        spin_lock_init(&c->ec_stripes_heap_lock);
 
        seqcount_init(&c->gc_pos_lock);
index 9b1ffbf96e14784a63527ff6128ee925564eee8a..b5ce336f00ca06382d6f7c99afbe5936b666a678 100644 (file)
@@ -203,6 +203,8 @@ read_attribute(new_stripes);
 read_attribute(io_timers_read);
 read_attribute(io_timers_write);
 
+read_attribute(data_op_data_progress);
+
 #ifdef CONFIG_BCACHEFS_TESTS
 write_attribute(perf_test);
 #endif /* CONFIG_BCACHEFS_TESTS */
@@ -239,6 +241,37 @@ static size_t bch2_btree_avg_write_size(struct bch_fs *c)
        return nr ? div64_u64(sectors, nr) : 0;
 }
 
+static long stats_to_text(struct printbuf *out, struct bch_fs *c,
+                         struct bch_move_stats *stats)
+{
+       pr_buf(out, "%s: data type %s btree_id %s position: ",
+               stats->name,
+               bch2_data_types[stats->data_type],
+               bch2_btree_ids[stats->btree_id]);
+       bch2_bpos_to_text(out, stats->pos);
+       pr_buf(out, "%s", "\n");
+
+       return 0;
+}
+
+static long data_progress_to_text(struct printbuf *out, struct bch_fs *c)
+{
+       long ret = 0;
+       struct bch_move_stats *iter;
+
+       mutex_lock(&c->data_progress_lock);
+
+       if (list_empty(&c->data_progress_list))
+               pr_buf(out, "%s", "no progress to report\n");
+       else
+               list_for_each_entry(iter, &c->data_progress_list, list) {
+                       stats_to_text(out, c, iter);
+               }
+
+       mutex_unlock(&c->data_progress_lock);
+       return ret;
+}
+
 static int fs_alloc_debug_to_text(struct printbuf *out, struct bch_fs *c)
 {
        struct bch_fs_usage_online *fs_usage = bch2_fs_usage_read(c);
@@ -434,6 +467,11 @@ SHOW(bch2_fs)
                return out.pos - buf;
        }
 
+       if (attr == &sysfs_data_op_data_progress) {
+               data_progress_to_text(&out, c);
+               return out.pos - buf;
+       }
+
        return 0;
 }
 
@@ -596,6 +634,8 @@ struct attribute *bch2_fs_internal_files[] = {
        &sysfs_io_timers_read,
        &sysfs_io_timers_write,
 
+       &sysfs_data_op_data_progress,
+
        &sysfs_internal_uuid,
        NULL
 };