From: James Simmons Date: Mon, 25 Oct 2021 20:56:31 +0000 (-0400) Subject: LU-14927 osd: share brw_stats code between OSD back ends. X-Git-Tag: 2.14.56~93 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=8a84c7f9c7d65f6f880be6fe4d94fca26a405d81;hp=a15a5432f8063e3a04a87d74eafac0060a8f9d26 LU-14927 osd: share brw_stats code between OSD back ends. Both the ldiskfs and ZFS OSD backend handle brw_stats. With the stricter GPL requirement ZFS can no longer carry the brw_stats code. So move the common code to lprocfs_status_server.c as well as move brw_stats to debugfs as well. Change-Id: I294e5df3557552266dd3a02d3bc9844c42c01f60 Signed-off-by: James Simmons Reviewed-on: https://review.whamcloud.com/44690 Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Reviewed-by: Aurelien Degremont Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h index 7fc41b1..5c7ddb2 100644 --- a/lustre/include/lprocfs_status.h +++ b/lustre/include/lprocfs_status.h @@ -103,29 +103,6 @@ struct obd_histogram { }; enum { - BRW_R_PAGES = 0, - BRW_W_PAGES, - BRW_R_RPC_HIST, - BRW_W_RPC_HIST, - BRW_R_IO_TIME, - BRW_W_IO_TIME, - BRW_R_DISCONT_PAGES, - BRW_W_DISCONT_PAGES, - BRW_R_DISCONT_BLOCKS, - BRW_W_DISCONT_BLOCKS, - BRW_R_DISK_IOSIZE, - BRW_W_DISK_IOSIZE, - BRW_R_DIO_FRAGS, - BRW_W_DIO_FRAGS, - BRW_LAST, -}; - -struct brw_stats { - ktime_t bs_init; - struct obd_histogram bs_hist[BRW_LAST]; -}; - -enum { RENAME_SAMEDIR_SIZE = 0, RENAME_CROSSDIR_SRC_SIZE, RENAME_CROSSDIR_TGT_SIZE, @@ -408,6 +385,42 @@ enum lprocfs_extra_opc { EXTRA_LAST_OPC }; +#ifdef HAVE_SERVER_SUPPORT +enum brw_rw_stats { + BRW_R_PAGES = 0, + BRW_W_PAGES, + BRW_R_DISCONT_PAGES, + BRW_W_DISCONT_PAGES, + BRW_R_DISCONT_BLOCKS, + BRW_W_DISCONT_BLOCKS, + BRW_R_DIO_FRAGS, + BRW_W_DIO_FRAGS, + BRW_R_RPC_HIST, + BRW_W_RPC_HIST, + BRW_R_IO_TIME, + BRW_W_IO_TIME, + BRW_R_DISK_IOSIZE, + BRW_W_DISK_IOSIZE, + BRW_RW_STATS_NUM, +}; + +struct brw_stats_props { + const char *bsp_name; + const char *bsp_units; + bool bsp_scale; +}; + +struct brw_stats { + ktime_t bs_init; + struct obd_histogram bs_hist[BRW_RW_STATS_NUM]; + struct brw_stats_props bs_props[BRW_RW_STATS_NUM / 2]; +}; + +void ldebugfs_register_osd_stats(struct dentry *parent, + struct brw_stats *brw_stats, + struct lprocfs_stats *stats); +#endif /* HAVE_SERVER_SUPPORT */ + #define EXTRA_FIRST_OPC LDLM_GLIMPSE_ENQUEUE /* class_obd.c */ extern struct proc_dir_entry *proc_lustre_root; @@ -415,7 +428,6 @@ extern struct dentry *debugfs_lustre_root; extern struct kset *lustre_kset; struct obd_device; -struct obd_histogram; #define JOBSTATS_JOBID_VAR_MAX_LEN 20 #define JOBSTATS_DISABLE "disable" diff --git a/lustre/obdclass/lprocfs_status_server.c b/lustre/obdclass/lprocfs_status_server.c index 8584b1b..7a78959 100644 --- a/lustre/obdclass/lprocfs_status_server.c +++ b/lustre/obdclass/lprocfs_status_server.c @@ -670,6 +670,142 @@ void lprocfs_free_obd_stats(struct obd_device *obd) } EXPORT_SYMBOL(lprocfs_free_obd_stats); +static void display_brw_stats(struct seq_file *seq, const char *name, + const char *units, struct obd_histogram *read, + struct obd_histogram *write, bool scale) +{ + unsigned long read_tot, write_tot, r, w, read_cum = 0, write_cum = 0; + unsigned int i; + + seq_printf(seq, "\n%26s read | write\n", " "); + seq_printf(seq, "%-22s %-5s %% cum %% | %-11s %% cum %%\n", + name, units, units); + + read_tot = lprocfs_oh_sum(read); + write_tot = lprocfs_oh_sum(write); + + if (!read_tot && !write_tot) + return; + + for (i = 0; i < OBD_HIST_MAX; i++) { + r = read->oh_buckets[i]; + w = write->oh_buckets[i]; + read_cum += r; + write_cum += w; + if (read_cum == 0 && write_cum == 0) + continue; + + if (!scale) + seq_printf(seq, "%u", i); + else if (i < 10) + seq_printf(seq, "%lu", BIT(i)); + else if (i < 20) + seq_printf(seq, "%luK", BIT(i - 10)); + else + seq_printf(seq, "%luM", BIT(i - 20)); + + seq_printf(seq, ":\t\t%10lu %3u %3u | %4lu %3u %3u\n", + r, pct(r, read_tot), pct(read_cum, read_tot), + w, pct(w, write_tot), pct(write_cum, write_tot)); + + if (read_cum == read_tot && write_cum == write_tot) + break; + } +} + +static const struct brw_stats_props brw_props[] = { + { .bsp_name = "pages per bulk r/w", + .bsp_units = "rpcs", + .bsp_scale = true }, + { .bsp_name = "discontiguous pages", + .bsp_units = "rpcs", + .bsp_scale = false }, + { .bsp_name = "discontiguous blocks", + .bsp_units = "rpcs", + .bsp_scale = false }, + { .bsp_name = "disk fragmented I/Os", + .bsp_units = "ios", + .bsp_scale = false }, + { .bsp_name = "disk I/Os in flight", + .bsp_units = "ios", + .bsp_scale = false }, + { .bsp_name = "I/O time (1/1000s)", + .bsp_units = "ios", + .bsp_scale = true }, + { .bsp_name = "disk I/O size", + .bsp_units = "ios", + .bsp_scale = true }, +}; + +static int brw_stats_seq_show(struct seq_file *seq, void *v) +{ + struct brw_stats *brw_stats = seq->private; + int i; + + /* this sampling races with updates */ + lprocfs_stats_header(seq, ktime_get(), brw_stats->bs_init, 25, ":", 1); + + for (i = 0; i < ARRAY_SIZE(brw_stats->bs_props); i++) { + if (!brw_stats->bs_props[i].bsp_name) + continue; + + display_brw_stats(seq, brw_stats->bs_props[i].bsp_name, + brw_stats->bs_props[i].bsp_units, + &brw_stats->bs_hist[i * 2], + &brw_stats->bs_hist[i * 2 + 1], + brw_stats->bs_props[i].bsp_scale); + } + + return 0; +} + +static ssize_t brw_stats_seq_write(struct file *file, + const char __user *buf, + size_t len, loff_t *off) +{ + struct seq_file *seq = file->private_data; + struct brw_stats *brw_stats = seq->private; + int i; + + for (i = 0; i < BRW_RW_STATS_NUM; i++) + lprocfs_oh_clear(&brw_stats->bs_hist[i]); + + return len; +} + +LDEBUGFS_SEQ_FOPS(brw_stats); + +void ldebugfs_register_osd_stats(struct dentry *parent, + struct brw_stats *brw_stats, + struct lprocfs_stats *stats) +{ + int i; + + LASSERT(brw_stats); + brw_stats->bs_init = ktime_get(); + for (i = 0; i < BRW_RW_STATS_NUM; i++) { + struct brw_stats_props *props = brw_stats->bs_props; + + spin_lock_init(&brw_stats->bs_hist[i].oh_lock); + if (i % 2) { + props[i / 2].bsp_name = brw_props[i / 2].bsp_name; + props[i / 2].bsp_units = brw_props[i / 2].bsp_units; + props[i / 2].bsp_scale = brw_props[i / 2].bsp_scale; + } + } + + if (!parent) + return; + + debugfs_create_file("brw_stats", 0644, parent, brw_stats, + &brw_stats_fops); + + if (stats) + debugfs_create_file("stats", 0644, parent, stats, + &ldebugfs_stats_seq_fops); +} +EXPORT_SYMBOL(ldebugfs_register_osd_stats); + int lprocfs_hash_seq_show(struct seq_file *m, void *data) { struct obd_device *obd = m->private; diff --git a/lustre/osd-ldiskfs/osd_lproc.c b/lustre/osd-ldiskfs/osd_lproc.c index 91d3b05..e2cc801 100644 --- a/lustre/osd-ldiskfs/osd_lproc.c +++ b/lustre/osd-ldiskfs/osd_lproc.c @@ -39,8 +39,6 @@ #include "osd_internal.h" -#ifdef CONFIG_PROC_FS - void osd_brw_stats_update(struct osd_device *osd, struct osd_iobuf *iobuf) { struct brw_stats *bs = &osd->od_brw_stats; @@ -77,121 +75,13 @@ void osd_brw_stats_update(struct osd_device *osd, struct osd_iobuf *iobuf) lprocfs_oh_tally(&bs->bs_hist[BRW_R_DISCONT_BLOCKS+rw], discont_blocks); } -static void display_brw_stats(struct seq_file *seq, char *name, char *units, - struct obd_histogram *read, struct obd_histogram *write, int scale) -{ - unsigned long read_tot, write_tot, r, w, read_cum = 0, write_cum = 0; - int i; - - seq_printf(seq, "\n%26s read | write\n", " "); - seq_printf(seq, "%-22s %-5s %% cum %% | %-11s %% cum %%\n", - name, units, units); - - read_tot = lprocfs_oh_sum(read); - write_tot = lprocfs_oh_sum(write); - for (i = 0; i < OBD_HIST_MAX; i++) { - r = read->oh_buckets[i]; - w = write->oh_buckets[i]; - read_cum += r; - write_cum += w; - if (read_cum == 0 && write_cum == 0) - continue; - - if (!scale) - seq_printf(seq, "%u", i); - else if (i < 10) - seq_printf(seq, "%u", scale << i); - else if (i < 20) - seq_printf(seq, "%uK", scale << (i-10)); - else - seq_printf(seq, "%uM", scale << (i-20)); - - seq_printf(seq, ":\t\t%10lu %3u %3u | %4lu %3u %3u\n", - r, pct(r, read_tot), pct(read_cum, read_tot), - w, pct(w, write_tot), pct(write_cum, write_tot)); - - if (read_cum == read_tot && write_cum == write_tot) - break; - } -} - -static void brw_stats_show(struct seq_file *seq, struct brw_stats *brw_stats) -{ - /* this sampling races with updates */ - lprocfs_stats_header(seq, ktime_get(), brw_stats->bs_init, 25, ":", 1); - - display_brw_stats(seq, "pages per bulk r/w", "rpcs", - &brw_stats->bs_hist[BRW_R_PAGES], - &brw_stats->bs_hist[BRW_W_PAGES], 1); - - display_brw_stats(seq, "discontiguous pages", "rpcs", - &brw_stats->bs_hist[BRW_R_DISCONT_PAGES], - &brw_stats->bs_hist[BRW_W_DISCONT_PAGES], 0); - - display_brw_stats(seq, "discontiguous blocks", "rpcs", - &brw_stats->bs_hist[BRW_R_DISCONT_BLOCKS], - &brw_stats->bs_hist[BRW_W_DISCONT_BLOCKS], 0); - - display_brw_stats(seq, "disk fragmented I/Os", "ios", - &brw_stats->bs_hist[BRW_R_DIO_FRAGS], - &brw_stats->bs_hist[BRW_W_DIO_FRAGS], 0); - - display_brw_stats(seq, "disk I/Os in flight", "ios", - &brw_stats->bs_hist[BRW_R_RPC_HIST], - &brw_stats->bs_hist[BRW_W_RPC_HIST], 0); - - display_brw_stats(seq, "I/O time (1/1000s)", "ios", - &brw_stats->bs_hist[BRW_R_IO_TIME], - &brw_stats->bs_hist[BRW_W_IO_TIME], 1); - - display_brw_stats(seq, "disk I/O size", "ios", - &brw_stats->bs_hist[BRW_R_DISK_IOSIZE], - &brw_stats->bs_hist[BRW_W_DISK_IOSIZE], 1); -} - -static int osd_brw_stats_seq_show(struct seq_file *seq, void *v) -{ - struct osd_device *osd = seq->private; - - brw_stats_show(seq, &osd->od_brw_stats); - - return 0; -} - -static ssize_t osd_brw_stats_seq_write(struct file *file, - const char __user *buf, - size_t len, loff_t *off) -{ - struct seq_file *seq = file->private_data; - struct osd_device *osd = seq->private; - int i; - - for (i = 0; i < BRW_LAST; i++) - lprocfs_oh_clear(&osd->od_brw_stats.bs_hist[i]); - osd->od_brw_stats.bs_init = ktime_get(); - - return len; -} - -LPROC_SEQ_FOPS(osd_brw_stats); - static int osd_stats_init(struct osd_device *osd) { - int i, result; + int result = -ENOMEM; ENTRY; - osd->od_brw_stats.bs_init = ktime_get(); - - for (i = 0; i < BRW_LAST; i++) - spin_lock_init(&osd->od_brw_stats.bs_hist[i].oh_lock); - osd->od_stats = lprocfs_alloc_stats(LPROC_OSD_LAST, 0); - if (osd->od_stats != NULL) { - result = lprocfs_register_stats(osd->od_proc_entry, "stats", - osd->od_stats); - if (result) - GOTO(out, result); - + if (osd->od_stats) { lprocfs_counter_init(osd->od_stats, LPROC_OSD_GET_PAGE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_CNTR_STDDEV, "get_page", "usec"); @@ -218,13 +108,13 @@ static int osd_stats_init(struct osd_device *osd) LPROCFS_CNTR_AVGMINMAX, "thandle closing", "usec"); #endif - result = lprocfs_seq_create(osd->od_proc_entry, "brw_stats", - 0644, &osd_brw_stats_fops, osd); - } else - result = -ENOMEM; + result = 0; + } -out: - RETURN(result); + ldebugfs_register_osd_stats(osd->od_dt_dev.dd_debugfs_entry, + &osd->od_brw_stats, osd->od_stats); + + RETURN(result); } static ssize_t fstype_show(struct kobject *kobj, struct attribute *attr, @@ -946,4 +836,3 @@ int osd_procfs_fini(struct osd_device *osd) return dt_tunables_fini(&osd->od_dt_dev); } -#endif diff --git a/lustre/osd-zfs/osd_lproc.c b/lustre/osd-zfs/osd_lproc.c index 01858f5..f865343 100644 --- a/lustre/osd-zfs/osd_lproc.c +++ b/lustre/osd-zfs/osd_lproc.c @@ -43,121 +43,13 @@ #include "osd_internal.h" -#ifdef CONFIG_PROC_FS - -static void display_brw_stats(struct seq_file *seq, char *name, char *units, - struct obd_histogram *read, - struct obd_histogram *write, int scale) -{ - unsigned long read_tot, write_tot, r, w, read_cum = 0, write_cum = 0; - int i; - - seq_printf(seq, "\n%26s read | write\n", " "); - seq_printf(seq, "%-22s %-5s %% cum %% | %-11s %% cum %%\n", - name, units, units); - - read_tot = lprocfs_oh_sum(read); - write_tot = lprocfs_oh_sum(write); - for (i = 0; i < OBD_HIST_MAX; i++) { - r = read->oh_buckets[i]; - w = write->oh_buckets[i]; - read_cum += r; - write_cum += w; - if (read_cum == 0 && write_cum == 0) - continue; - - if (!scale) - seq_printf(seq, "%u", i); - else if (i < 10) - seq_printf(seq, "%u", scale << i); - else if (i < 20) - seq_printf(seq, "%uK", scale << (i-10)); - else - seq_printf(seq, "%uM", scale << (i-20)); - - seq_printf(seq, ":\t\t%10lu %3u %3u | %4lu %3u %3u\n", - r, pct(r, read_tot), pct(read_cum, read_tot), - w, pct(w, write_tot), pct(write_cum, write_tot)); - - if (read_cum == read_tot && write_cum == write_tot) - break; - } -} - -static void brw_stats_show(struct seq_file *seq, struct brw_stats *brw_stats) -{ - /* this sampling races with updates */ - lprocfs_stats_header(seq, ktime_get(), brw_stats->bs_init, 25, ":", 1); - - display_brw_stats(seq, "pages per bulk r/w", "rpcs", - &brw_stats->bs_hist[BRW_R_PAGES], - &brw_stats->bs_hist[BRW_W_PAGES], 1); - - display_brw_stats(seq, "discontiguous pages", "rpcs", - &brw_stats->bs_hist[BRW_R_DISCONT_PAGES], - &brw_stats->bs_hist[BRW_W_DISCONT_PAGES], 0); -#if 0 - display_brw_stats(seq, "discontiguous blocks", "rpcs", - &brw_stats->bs_hist[BRW_R_DISCONT_BLOCKS], - &brw_stats->bs_hist[BRW_W_DISCONT_BLOCKS], 0); - - display_brw_stats(seq, "disk fragmented I/Os", "ios", - &brw_stats->bs_hist[BRW_R_DIO_FRAGS], - &brw_stats->bs_hist[BRW_W_DIO_FRAGS], 0); -#endif - display_brw_stats(seq, "disk I/Os in flight", "ios", - &brw_stats->bs_hist[BRW_R_RPC_HIST], - &brw_stats->bs_hist[BRW_W_RPC_HIST], 0); - - display_brw_stats(seq, "I/O time (1/1000s)", "ios", - &brw_stats->bs_hist[BRW_R_IO_TIME], - &brw_stats->bs_hist[BRW_W_IO_TIME], 1); - - display_brw_stats(seq, "disk I/O size", "ios", - &brw_stats->bs_hist[BRW_R_DISK_IOSIZE], - &brw_stats->bs_hist[BRW_W_DISK_IOSIZE], 1); -} - -static int osd_brw_stats_seq_show(struct seq_file *seq, void *v) -{ - struct osd_device *osd = seq->private; - - brw_stats_show(seq, &osd->od_brw_stats); - - return 0; -} - -static ssize_t osd_brw_stats_seq_write(struct file *file, - const char __user *buf, - size_t len, loff_t *off) -{ - struct seq_file *seq = file->private_data; - struct osd_device *osd = seq->private; - int i; - - for (i = 0; i < BRW_LAST; i++) - lprocfs_oh_clear(&osd->od_brw_stats.bs_hist[i]); - - return len; -} - -LPROC_SEQ_FOPS(osd_brw_stats); - static int osd_stats_init(struct osd_device *osd) { - int result, i; - ENTRY; - - for (i = 0; i < BRW_LAST; i++) - spin_lock_init(&osd->od_brw_stats.bs_hist[i].oh_lock); + int result = -ENOMEM; + ENTRY; osd->od_stats = lprocfs_alloc_stats(LPROC_OSD_LAST, 0); - if (osd->od_stats != NULL) { - result = lprocfs_register_stats(osd->od_proc_entry, "stats", - osd->od_stats); - if (result) - GOTO(out, result); - + if (osd->od_stats) { lprocfs_counter_init(osd->od_stats, LPROC_OSD_GET_PAGE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_CNTR_STDDEV, "get_page", "usec"); @@ -193,13 +85,15 @@ static int osd_stats_init(struct osd_device *osd) LPROCFS_CNTR_AVGMINMAX, "thandle_closing", "usec"); #endif - result = lprocfs_seq_create(osd->od_proc_entry, "brw_stats", - 0644, &osd_brw_stats_fops, osd); - } else { - result = -ENOMEM; + result = 0; } -out: + ldebugfs_register_osd_stats(osd->od_dt_dev.dd_debugfs_entry, + &osd->od_brw_stats, osd->od_stats); + /* These fields are not supported for ZFS */ + osd->od_brw_stats.bs_props[BRW_R_DISCONT_BLOCKS / 2].bsp_name = NULL; + osd->od_brw_stats.bs_props[BRW_R_DIO_FRAGS / 2].bsp_name = NULL; + RETURN(result); } @@ -523,5 +417,3 @@ int osd_procfs_fini(struct osd_device *osd) return dt_tunables_fini(&osd->od_dt_dev); } - -#endif