git: c263dd413ca0 - main - gstat: Refactor and polish. Added option for {kB/MB/GB} per second.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 27 Jun 2026 11:28:44 UTC
The branch main has been updated by phk:
URL: https://cgit.FreeBSD.org/src/commit/?id=c263dd413ca0b43b4513e6e6dd8ed64c0eb9c3aa
commit c263dd413ca0b43b4513e6e6dd8ed64c0eb9c3aa
Author: Poul-Henning Kamp <phk@FreeBSD.org>
AuthorDate: 2026-06-27 11:26:18 +0000
Commit: Poul-Henning Kamp <phk@FreeBSD.org>
CommitDate: 2026-06-27 11:28:33 +0000
gstat: Refactor and polish. Added option for {kB/MB/GB} per second.
---
usr.sbin/gstat/gstat.8 | 24 +-
usr.sbin/gstat/gstat.c | 770 ++++++++++++++++++++++++++-----------------------
2 files changed, 437 insertions(+), 357 deletions(-)
diff --git a/usr.sbin/gstat/gstat.8 b/usr.sbin/gstat/gstat.8
index e882aa75b8d7..602376d5fd0d 100644
--- a/usr.sbin/gstat/gstat.8
+++ b/usr.sbin/gstat/gstat.8
@@ -78,6 +78,12 @@ Only devices with the names matching
will be displayed.
The format of the regular expression is described in
.Xr re_format 7 .
+.It Fl g
+Show Gigabytes
+.It Fl k
+Show kilobytes
+.It Fl m
+Show Megabytes
.It Fl I Ar interval
Refresh the
.Nm
@@ -96,7 +102,7 @@ Enable display of statistics for other operations
.It Fl p
Only display physical providers (those with rank of 1).
.It Fl s
-Enable blocks' size statistics.
+Enable average block size.
.El
.Sh INTERACTIVE COMMANDS
These commands are currently recognized if
@@ -107,17 +113,33 @@ is not running in batch mode:
Halve the update interval.
.It Ic >
Double the update interval.
+.It Ic 1
+Set update interval to one second
.It Ic c
Toggle display of
.Xr geom 4
consumers.
+.It Ic d
+Toggle display BIO_DELETE
.It Ic f
Display only devices with the names matching regular expression filter
(prompt for filter).
.It Ic F
Remove device filter.
+.It Ic g
+Show gigabytes.
+.It Ic k
+Show kilobytes.
+.It Ic m
+Show megabytes.
+.It Ic o
+Toggle display other (BIO_FLUSH) operations.
+.It Ic p
+Toggle display other only primary providers.
.It Ic q
Quit
+.It Ic s
+Toggle average block size.
.Nm .
.El
.Sh EXIT STATUS
diff --git a/usr.sbin/gstat/gstat.c b/usr.sbin/gstat/gstat.c
index c650f7120a40..11616d263272 100644
--- a/usr.sbin/gstat/gstat.c
+++ b/usr.sbin/gstat/gstat.c
@@ -44,6 +44,7 @@
#include <libgeom.h>
#include <paths.h>
#include <regex.h>
+#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -51,20 +52,190 @@
#include <sysexits.h>
#include <unistd.h>
+#define HIGH_PCT_BUSY_THRESH 80
+#define MEDIUM_PCT_BUSY_THRESH 50
+
static int flag_a, flag_b, flag_B, flag_c, flag_C, flag_d, flag_o, flag_p,
flag_s;
static int flag_I = 1000000;
-#define HIGH_PCT_BUSY_THRESH 80
-#define MEDIUM_PCT_BUSY_THRESH 50
-#define PRINTMSG(...) do { \
- if ((flag_b && !loop) || (flag_B)) \
- printf(__VA_ARGS__); \
- else if (!flag_b) \
- printw(__VA_ARGS__); \
- } while(0)
+static int quit;
+static int max_flen;
+static History *hist;
+static EditLine *el;
+static HistEvent hist_ev;
+static regex_t f_re;
+static char pf_s[100];
+static char f_s[100];
+static uintmax_t loop;
+static double dt;
+static double byte_scale = 1024;
+static const char *byte_unit = "k";
+
+struct kstat {
+ long double transfers_per_second;
+ long double mb_per_second;
+ long double ms_per_transaction;
+ long double kb_per_transfer;
+};
+
+static void __dead2
+usage(void)
+{
+ fprintf(stderr,
+ "usage: gstat [-abBcCdgkmops] [-f filter] [-I interval]\n");
+ exit(EX_USAGE);
+ /* NOTREACHED */
+}
+
+static void
+use_kb(void)
+{
+ byte_scale = 1024;
+ byte_unit = "k";
+}
+
+static void
+use_mb(void)
+{
+ byte_scale = 1;
+ byte_unit = "M";
+}
+
+static void
+use_gb(void)
+{
+ byte_scale = 1.0/1024;
+ byte_unit = "G";
+}
+
+static void
+printer(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (flag_B || (flag_b && loop == 2))
+ vprintf(fmt, ap);
+ if (!flag_b)
+ vw_printw(stdscr, fmt, ap);
+ va_end(ap);
+}
-static void usage(void) __dead2;
+static void
+text_fld_header(const char *k)
+{
+ if (flag_s)
+ printer(" %s/s kB %sBps ms/%s ", k, byte_unit, k);
+ else
+ printer(" %s/s %sBps ms/%s ", k, byte_unit, k);
+}
+
+static void
+text_header(void)
+{
+ int curx = 0, cury = 0;
+ int maxx = 0, maxy = 0;
+
+ if (!flag_b)
+ move(0,0);
+ printer("dT: %5.3fs w: %.3fs", dt,
+ (float)flag_I / 1000000);
+ if (f_s[0] != '\0') {
+ printer(" filter: ");
+ if (!flag_b) {
+ getyx(stdscr, cury, curx);
+ (void)cury;
+ getmaxyx(stdscr, maxy, maxx);
+ (void)maxy;
+ }
+ strlcpy(pf_s, f_s, sizeof(pf_s));
+ max_flen = maxx - curx - 1;
+ if ((int)strlen(f_s) > max_flen && max_flen >= 0) {
+ if (max_flen > 3)
+ pf_s[max_flen - 3] = '.';
+ if (max_flen > 2)
+ pf_s[max_flen - 2] = '.';
+ if (max_flen > 1)
+ pf_s[max_flen - 1] = '.';
+ pf_s[max_flen] = '\0';
+ }
+ printer("%s", pf_s);
+ }
+
+ if (!flag_b)
+ clrtoeol();
+ printer("\n");
+
+ printer(" L(q) ops/s ");
+ text_fld_header("r");
+ text_fld_header("w");
+ if (flag_d)
+ text_fld_header("d");
+ if (flag_o)
+ printer(" o/s ms/o ");
+ printer("%%busy Name");
+ if (!flag_b)
+ clrtoeol();
+ printer("\n");
+}
+
+static void
+print_kstat_text(const struct kstat *ks, int other)
+{
+ printer(" %6.0f", (double)ks->transfers_per_second);
+ if (flag_s && !other)
+ printer(" %6.0f", (double)ks->kb_per_transfer);
+ if (!other)
+ printer(" %6.0f", (double)ks->mb_per_second * byte_scale);
+ if (ks->ms_per_transaction < 100)
+ printer(" %6.3f", (double)ks->ms_per_transaction);
+ else if (ks->ms_per_transaction < 1000)
+ printer(" %6.2f", (double)ks->ms_per_transaction);
+ else if (ks->ms_per_transaction < 10000)
+ printer(" %6.1f", (double)ks->ms_per_transaction);
+ else
+ printer(" %6.0f", (double)ks->ms_per_transaction);
+}
+
+static void
+print_head_csv(void)
+{
+
+ printf("timestamp,name,q-depth,total_ops/s");
+ if (flag_s) {
+ printf(",read/s,read_sz-KiB");
+ printf(",read-KiB/s,ms/read");
+ printf(",write/s,write_sz-KiB");
+ printf(",write-KiB/s,ms/write");
+ } else {
+ printf(",read/s,read-KiB/s,ms/read");
+ printf(",write/s,write-KiB/s,ms/write");
+ }
+ if (flag_d) {
+ if (flag_s) {
+ printf(",delete/s,delete-sz-KiB");
+ printf(",delete-KiB/s,ms/delete");
+ } else {
+ printf(",delete/s,delete-KiB/s");
+ printf(",ms/delete");
+ }
+ }
+ if (flag_o)
+ printf(",other/s,ms/other");
+ printf(",%%busy\n");
+}
+
+static void
+print_kstat_csv(const struct kstat *ks, int other)
+{
+
+ printf(",%.0f", (double)ks->transfers_per_second);
+ if (flag_s && !other)
+ printf(",%.0f", (double)ks->kb_per_transfer);
+ if (!other)
+ printf(",%.0f", (double)ks->mb_per_second * 1024);
+ printf(",%.3f", (double)ks->ms_per_transaction);
+}
static const char*
el_prompt(void)
@@ -73,42 +244,167 @@ el_prompt(void)
return ("Filter: ");
}
+static void
+setup_interactive(void)
+{
+ short cf, cb;
+
+ /* Setup libedit */
+ hist = history_init();
+ if (hist == NULL)
+ err(EX_SOFTWARE, "history_init()");
+ history(hist, &hist_ev, H_SETSIZE, 100);
+ el = el_init("gstat", stdin, stdout, stderr);
+ if (el == NULL)
+ err(EX_SOFTWARE, "el_init");
+ el_set(el, EL_EDITOR, "emacs");
+ el_set(el, EL_SIGNAL, 1);
+ el_set(el, EL_HIST, history, hist);
+ el_set(el, EL_PROMPT, el_prompt);
+ if (f_s[0] != '\0')
+ history(hist, &hist_ev, H_ENTER, f_s);
+ /* Setup curses */
+ initscr();
+ start_color();
+ use_default_colors();
+ pair_content(0, &cf, &cb);
+ init_pair(1, COLOR_GREEN, cb);
+ init_pair(2, COLOR_MAGENTA, cb);
+ init_pair(3, COLOR_RED, cb);
+ cbreak();
+ noecho();
+ nonl();
+ nodelay(stdscr, 1);
+ intrflush(stdscr, FALSE);
+ keypad(stdscr, TRUE);
+}
+
+static int
+poll_input(void)
+{
+ int i, line_len;
+ char *p;
+ const char *line;
+ char tmp_f_s[100];
+ regex_t tmp_f_re;
+
+ i = getch();
+ if (i == ERR)
+ return (0);
+ switch (i) {
+ case '>':
+ flag_I *= 2;
+ break;
+ case '<':
+ flag_I /= 2;
+ if (flag_I < 1000)
+ flag_I = 1000;
+ break;
+ case '1':
+ flag_I = 1000000;
+ break;
+ case 'c':
+ flag_c = !flag_c;
+ break;
+ case 'd':
+ flag_d = !flag_d;
+ break;
+ case 'o':
+ flag_o = !flag_o;
+ break;
+ case 'f':
+ move(0,0);
+ clrtoeol();
+ refresh();
+ line = el_gets(el, &line_len);
+ if (line == NULL)
+ err(1, "el_gets");
+ if (line_len > 1)
+ history(hist, &hist_ev, H_ENTER, line);
+ strlcpy(tmp_f_s, line, sizeof(f_s));
+ if ((p = strchr(tmp_f_s, '\n')) != NULL)
+ *p = '\0';
+ /*
+ * Fix the terminal. We messed up
+ * curses idea of the screen by using
+ * libedit.
+ */
+ clear();
+ refresh();
+ cbreak();
+ noecho();
+ nonl();
+ if (regcomp(&tmp_f_re, tmp_f_s, REG_EXTENDED)
+ != 0) {
+ move(0, 0);
+ printw("Invalid filter");
+ refresh();
+ sleep(1);
+ } else {
+ strlcpy(f_s, tmp_f_s, sizeof(f_s));
+ f_re = tmp_f_re;
+ }
+ break;
+ case 'F':
+ f_s[0] = '\0';
+ break;
+ case 'g':
+ case 'G':
+ use_gb();
+ break;
+ case 'k':
+ case 'K':
+ use_kb();
+ break;
+ case 'm':
+ case 'M':
+ use_mb();
+ break;
+ case 'q':
+ quit = 1;
+ break;
+ case 'p':
+ flag_p = !flag_p;
+ break;
+ case 's':
+ flag_s = !flag_s;
+ break;
+ default:
+ break;
+ }
+ return (1);
+}
+
int
main(int argc, char **argv)
{
- int error, i, quit;
- int curx, cury, maxx, maxy, line_len, loop, max_flen, head_printed;
+ int error, i;
+ int curx, cury, maxx, maxy;
struct devstat *gsp, *gsq;
void *sp, *sq;
- double dt;
struct timespec tp, tq;
struct gmesh gmp;
struct gprovider *pp;
struct gconsumer *cp;
struct gident *gid;
- regex_t f_re, tmp_f_re;
- short cf, cb;
char *p;
- char f_s[100], pf_s[100], tmp_f_s[100];
char ts[100], g_name[4096];
- const char *line;
- long double ld[16];
- uint64_t u64;
- EditLine *el;
- History *hist;
- HistEvent hist_ev;
+ long double xfer_per_sec, busy_pct;
+ struct kstat krd, kwr, kfree, kother;
+ uint64_t queue_len;
+ memset(&kother, 0, sizeof kother);
hist = NULL;
el = NULL;
maxx = -1;
curx = -1;
- loop = 1;
+ loop = 0;
/* Turn on batch mode if output is not tty. */
if (!isatty(fileno(stdout)))
flag_b = 1;
f_s[0] = '\0';
- while ((i = getopt(argc, argv, "abBdcCf:I:ops")) != -1) {
+ while ((i = getopt(argc, argv, "abBcdCf:gI:kmops")) != -1) {
switch (i) {
case 'a':
flag_a = 1;
@@ -128,7 +424,6 @@ main(int argc, char **argv)
/* csv out implies repeating batch mode */
flag_b = 1;
flag_B = 1;
- head_printed = 0;
break;
case 'd':
flag_d = 1;
@@ -141,6 +436,9 @@ main(int argc, char **argv)
"Invalid filter - see re_format(7)");
strlcpy(f_s, optarg, sizeof(f_s));
break;
+ case 'g':
+ use_gb();
+ break;
case 'I':
p = NULL;
i = strtoul(optarg, &p, 0);
@@ -155,6 +453,12 @@ main(int argc, char **argv)
i *= 1;
flag_I = i;
break;
+ case 'k':
+ use_kb();
+ break;
+ case 'm':
+ use_mb();
+ break;
case 'o':
flag_o = 1;
break;
@@ -180,42 +484,16 @@ main(int argc, char **argv)
error = geom_stats_open();
if (error)
err(1, "geom_stats_open()");
- sq = NULL;
sq = geom_stats_snapshot_get();
if (sq == NULL)
err(1, "geom_stats_snapshot()");
- if (!flag_b) {
- /* Setup libedit */
- hist = history_init();
- if (hist == NULL)
- err(EX_SOFTWARE, "history_init()");
- history(hist, &hist_ev, H_SETSIZE, 100);
- el = el_init("gstat", stdin, stdout, stderr);
- if (el == NULL)
- err(EX_SOFTWARE, "el_init");
- el_set(el, EL_EDITOR, "emacs");
- el_set(el, EL_SIGNAL, 1);
- el_set(el, EL_HIST, history, hist);
- el_set(el, EL_PROMPT, el_prompt);
- if (f_s[0] != '\0')
- history(hist, &hist_ev, H_ENTER, f_s);
- /* Setup curses */
- initscr();
- start_color();
- use_default_colors();
- pair_content(0, &cf, &cb);
- init_pair(1, COLOR_GREEN, cb);
- init_pair(2, COLOR_MAGENTA, cb);
- init_pair(3, COLOR_RED, cb);
- cbreak();
- noecho();
- nonl();
- nodelay(stdscr, 1);
- intrflush(stdscr, FALSE);
- keypad(stdscr, TRUE);
- }
+ if (!flag_b)
+ setup_interactive();
+ if (flag_C)
+ print_head_csv();
geom_stats_snapshot_timestamp(sq, &tq);
for (quit = 0; !quit;) {
+ loop += 1;
sp = geom_stats_snapshot_get();
if (sp == NULL)
err(1, "geom_stats_snapshot()");
@@ -229,79 +507,11 @@ main(int argc, char **argv)
(void)snprintf(ts,sizeof(ts),
"%s.%.9ld",ts,tq.tv_nsec);
}
-
+ if (loop > 1 && !flag_C)
+ text_header();
+
geom_stats_snapshot_reset(sp);
geom_stats_snapshot_reset(sq);
- if (!flag_b)
- move(0,0);
- if (!flag_C)
- PRINTMSG("dT: %5.3fs w: %.3fs", dt,
- (float)flag_I / 1000000);
- if (!flag_C && f_s[0] != '\0') {
- PRINTMSG(" filter: ");
- if (!flag_b) {
- getyx(stdscr, cury, curx);
- getmaxyx(stdscr, maxy, maxx);
- }
- strlcpy(pf_s, f_s, sizeof(pf_s));
- max_flen = maxx - curx - 1;
- if ((int)strlen(f_s) > max_flen && max_flen >= 0) {
- if (max_flen > 3)
- pf_s[max_flen - 3] = '.';
- if (max_flen > 2)
- pf_s[max_flen - 2] = '.';
- if (max_flen > 1)
- pf_s[max_flen - 1] = '.';
- pf_s[max_flen] = '\0';
- }
- PRINTMSG("%s", pf_s);
- }
- if (!flag_C) {
- PRINTMSG("\n");
- PRINTMSG(" L(q) ops/s ");
- if (flag_s) {
- PRINTMSG(" r/s kB kBps ms/r ");
- PRINTMSG(" w/s kB kBps ms/w ");
- }
- else {
- PRINTMSG(" r/s kBps ms/r ");
- PRINTMSG(" w/s kBps ms/w ");
- }
- if (flag_d) {
- if (flag_s) {
- PRINTMSG(" d/s kB kBps");
- PRINTMSG(" ms/d ");
- } else
- PRINTMSG(" d/s kBps ms/d ");
- }
- if (flag_o)
- PRINTMSG(" o/s ms/o ");
- PRINTMSG("%%busy Name\n");
- } else if (flag_C && !head_printed) {
- PRINTMSG("timestamp,name,q-depth,total_ops/s");
- if (flag_s) {
- PRINTMSG(",read/s,read_sz-KiB");
- PRINTMSG(",read-KiB/s,ms/read");
- PRINTMSG(",write/s,write_sz-KiB");
- PRINTMSG(",write-KiB/s,ms/write");
- } else {
- PRINTMSG(",read/s,read-KiB/s,ms/read");
- PRINTMSG(",write/s,write-KiB/s,ms/write");
- }
- if (flag_d) {
- if (flag_s) {
- PRINTMSG(",delete/s,delete-sz-KiB");
- PRINTMSG(",delete-KiB/s,ms/delete");
- } else {
- PRINTMSG(",delete/s,delete-KiB/s");
- PRINTMSG(",ms/delete");
- }
- }
- if (flag_o)
- PRINTMSG(",other/s,ms/other");
- PRINTMSG(",%%busy\n");
- head_printed = 1;
- }
for (;;) {
gsp = geom_stats_snapshot_next(sp);
gsq = geom_stats_snapshot_next(sq);
@@ -339,50 +549,48 @@ main(int argc, char **argv)
continue;
}
if (gsp->sequence0 != gsp->sequence1) {
- /*
+ /*
* it is ok to skip entire line silently
* for CSV output
*/
if (!flag_C)
- PRINTMSG("*\n");
+ printer("*\n");
continue;
}
- devstat_compute_statistics(gsp, gsq, dt,
- DSM_QUEUE_LENGTH, &u64,
- DSM_TRANSFERS_PER_SECOND, &ld[0],
-
- DSM_TRANSFERS_PER_SECOND_READ, &ld[1],
- DSM_MB_PER_SECOND_READ, &ld[2],
- DSM_MS_PER_TRANSACTION_READ, &ld[3],
- DSM_TRANSFERS_PER_SECOND_WRITE, &ld[4],
- DSM_MB_PER_SECOND_WRITE, &ld[5],
- DSM_MS_PER_TRANSACTION_WRITE, &ld[6],
+#define CONVENIENCE(oper, kst) \
+ DSM_TRANSFERS_PER_SECOND_##oper, &kst.transfers_per_second, \
+ DSM_MB_PER_SECOND_##oper, &kst.mb_per_second, \
+ DSM_MS_PER_TRANSACTION_##oper, &kst.ms_per_transaction, \
+ DSM_KB_PER_TRANSFER_##oper, &kst.kb_per_transfer,
- DSM_BUSY_PCT, &ld[7],
+ devstat_compute_statistics(gsp, gsq, dt,
+ DSM_QUEUE_LENGTH, &queue_len,
+ DSM_TRANSFERS_PER_SECOND, &xfer_per_sec,
- DSM_TRANSFERS_PER_SECOND_FREE, &ld[8],
- DSM_MB_PER_SECOND_FREE, &ld[9],
- DSM_MS_PER_TRANSACTION_FREE, &ld[10],
+ CONVENIENCE(READ, krd)
+ CONVENIENCE(WRITE, kwr)
+ CONVENIENCE(FREE, kfree)
- DSM_TRANSFERS_PER_SECOND_OTHER, &ld[11],
- DSM_MS_PER_TRANSACTION_OTHER, &ld[12],
+ DSM_BUSY_PCT, &busy_pct,
- DSM_KB_PER_TRANSFER_READ, &ld[13],
- DSM_KB_PER_TRANSFER_WRITE, &ld[14],
- DSM_KB_PER_TRANSFER_FREE, &ld[15],
+ DSM_TRANSFERS_PER_SECOND_OTHER,
+ &kother.transfers_per_second,
+ DSM_MS_PER_TRANSACTION_OTHER,
+ &kother.ms_per_transaction,
DSM_NONE);
- if (flag_a && ld[7] < 0.1) {
- *gsq = *gsp;
+ *gsq = *gsp;
+ if (loop == 1)
+ continue;
+
+ if (flag_a && busy_pct < 0.1) {
continue;
}
/* store name for geom device */
- if (gid == NULL) {
- (void)snprintf(g_name, sizeof(g_name), "??");
- } else if (gid->lg_what == ISPROVIDER) {
+ if (gid->lg_what == ISPROVIDER) {
pp = gid->lg_ptr;
(void)snprintf(g_name, sizeof(g_name), "%s",
pp->lg_name);
@@ -391,231 +599,81 @@ main(int argc, char **argv)
(void)snprintf(g_name, sizeof(g_name),
"%s/%s/%s",
cp->lg_geom->lg_class->lg_name,
- cp->lg_geom->lg_name,
- cp->lg_provider->lg_name);
+ cp->lg_geom->lg_name,
+ cp->lg_provider->lg_name);
}
-
- if (flag_C) {
- PRINTMSG("%s", ts); /* timestamp */
- PRINTMSG(",%s", g_name); /* print name */
- PRINTMSG(",%ju", (uintmax_t)u64);
- PRINTMSG(",%.0f", (double)ld[0]);
- PRINTMSG(",%.0f", (double)ld[1]);
- if (flag_s)
- PRINTMSG(",%.0f", (double)ld[13]);
- PRINTMSG(",%.0f", (double)ld[2] * 1024);
- if (ld[3] > 1e3)
- PRINTMSG(",%.0f", (double)ld[3]);
- else if (ld[3] > 1e0)
- PRINTMSG(",%.1f", (double)ld[3]);
- else
- PRINTMSG(",%.3f", (double)ld[3]);
- PRINTMSG(",%.0f", (double)ld[4]);
- if (flag_s)
- PRINTMSG(",%.0f", (double)ld[14]);
- PRINTMSG(",%.0f", (double)ld[5] * 1024);
- if (ld[6] > 1e3)
- PRINTMSG(",%.0f", (double)ld[6]);
- else if (ld[6] > 1e0)
- PRINTMSG(",%.1f", (double)ld[6]);
- else
- PRINTMSG(",%.3f", (double)ld[6]);
-
- if (flag_d) {
- PRINTMSG(",%.0f", (double)ld[8]);
- if (flag_s)
- PRINTMSG(",%.0f",
- (double)ld[15]);
- PRINTMSG(",%.0f", (double)ld[9] * 1024);
- if (ld[10] > 1e3)
- PRINTMSG(",%.0f",
- (double)ld[10]);
- else if (ld[10] > 1e0)
- PRINTMSG(",%.1f",
- (double)ld[10]);
- else
- PRINTMSG(",%.3f",
- (double)ld[10]);
- }
- if (flag_o) {
- PRINTMSG(",%.0f", (double)ld[11]);
- if (ld[12] > 1e3)
- PRINTMSG(",%.0f",
- (double)ld[12]);
- else if (ld[12] > 1e0)
- PRINTMSG(",%.1f",
- (double)ld[12]);
- else
- PRINTMSG(",%.3f",
- (double)ld[12]);
- }
- PRINTMSG(",%.1lf", (double)ld[7]);
+ if (flag_C) {
+ printf("%s", ts); /* timestamp */
+ printf(",%s", g_name); /* print name */
+ printf(",%ju", (uintmax_t)queue_len);
+ printf(",%.0f", (double)xfer_per_sec);
+ print_kstat_csv(&krd, 0);
+ print_kstat_csv(&kwr, 0);
+ if (flag_d)
+ print_kstat_csv(&kfree, 0);
+ if (flag_o)
+ print_kstat_csv(&kother, 1);
+ printf(",%.1lf\n", (double)busy_pct);
} else {
- PRINTMSG(" %4ju", (uintmax_t)u64);
- PRINTMSG(" %6.0f", (double)ld[0]);
- PRINTMSG(" %6.0f", (double)ld[1]);
- if (flag_s)
- PRINTMSG(" %6.0f", (double)ld[13]);
- PRINTMSG(" %6.0f", (double)ld[2] * 1024);
- if (ld[3] > 1e3)
- PRINTMSG(" %6.0f", (double)ld[3]);
- else if (ld[3] > 1e0)
- PRINTMSG(" %6.1f", (double)ld[3]);
- else
- PRINTMSG(" %6.3f", (double)ld[3]);
- PRINTMSG(" %6.0f", (double)ld[4]);
- if (flag_s)
- PRINTMSG(" %6.0f", (double)ld[14]);
- PRINTMSG(" %6.0f", (double)ld[5] * 1024);
- if (ld[6] > 1e3)
- PRINTMSG(" %6.0f", (double)ld[6]);
- else if (ld[6] > 1e0)
- PRINTMSG(" %6.1f", (double)ld[6]);
- else
- PRINTMSG(" %6.3f", (double)ld[6]);
-
- if (flag_d) {
- PRINTMSG(" %6.0f", (double)ld[8]);
- if (flag_s)
- PRINTMSG(" %6.0f",
- (double)ld[15]);
- PRINTMSG(" %6.0f",
- (double)ld[9] * 1024);
- if (ld[10] > 1e3)
- PRINTMSG(" %6.0f",
- (double)ld[10]);
- else if (ld[10] > 1e0)
- PRINTMSG(" %6.1f",
- (double)ld[10]);
- else
- PRINTMSG(" %6.3f",
- (double)ld[10]);
- }
+ printer(" %4ju", (uintmax_t)queue_len);
+ printer(" %6.0f", (double)xfer_per_sec);
- if (flag_o) {
- PRINTMSG(" %6.0f", (double)ld[11]);
- if (ld[12] > 1e3)
- PRINTMSG(" %6.0f",
- (double)ld[12]);
- else if (ld[12] > 1e0)
- PRINTMSG(" %6.1f",
- (double)ld[12]);
+ print_kstat_text(&krd, 0);
+ print_kstat_text(&kwr, 0);
+ if (flag_d)
+ print_kstat_text(&kfree, 0);
+ if (flag_o)
+ print_kstat_text(&kother, 1);
+ if (!flag_b) {
+ if (busy_pct > HIGH_PCT_BUSY_THRESH)
+ i = 3;
+ else if (busy_pct > MEDIUM_PCT_BUSY_THRESH)
+ i = 2;
else
- PRINTMSG(" %6.3f",
- (double)ld[12]);
+ i = 1;
+ attron(COLOR_PAIR(i));
}
-
- if (ld[7] > HIGH_PCT_BUSY_THRESH)
- i = 3;
- else if (ld[7] > MEDIUM_PCT_BUSY_THRESH)
- i = 2;
- else
- i = 1;
+ printer(" %6.1lf", (double)busy_pct);
if (!flag_b)
- attron(COLOR_PAIR(i));
- PRINTMSG(" %6.1lf", (double)ld[7]);
- if (!flag_b) {
attroff(COLOR_PAIR(i));
- PRINTMSG("|");
- } else
- PRINTMSG(" ");
- PRINTMSG(" %s", g_name);
+
+ printer(" %s", g_name);
if (!flag_b)
clrtoeol();
+ printer("\n");
}
- PRINTMSG("\n");
- *gsq = *gsp;
}
geom_stats_snapshot_free(sp);
- if (flag_b) {
- /* We loop extra to make sure we get the information. */
- if (!loop)
+ if (flag_b || flag_C) {
+ if (!flag_B && !flag_C && loop == 2)
break;
- if (!flag_B)
- loop = 0;
- else
- if (fflush(stdout) == EOF)
- goto out;
- usleep(flag_I);
- continue;
- }
- getyx(stdscr, cury, curx);
- getmaxyx(stdscr, maxy, maxx);
- clrtobot();
- if (maxy - 1 <= cury)
- move(maxy - 1, 0);
- refresh();
- usleep(flag_I);
- while((i = getch()) != ERR) {
- switch (i) {
- case '>':
- flag_I *= 2;
- break;
- case '<':
- flag_I /= 2;
- if (flag_I < 1000)
- flag_I = 1000;
- break;
- case 'c':
- flag_c = !flag_c;
- break;
- case 'f':
- move(0,0);
- clrtoeol();
- refresh();
- line = el_gets(el, &line_len);
- if (line == NULL)
- err(1, "el_gets");
- if (line_len > 1)
- history(hist, &hist_ev, H_ENTER, line);
- strlcpy(tmp_f_s, line, sizeof(f_s));
- if ((p = strchr(tmp_f_s, '\n')) != NULL)
- *p = '\0';
- /*
- * Fix the terminal. We messed up
- * curses idea of the screen by using
- * libedit.
- */
- clear();
- refresh();
- cbreak();
- noecho();
- nonl();
- if (regcomp(&tmp_f_re, tmp_f_s, REG_EXTENDED)
- != 0) {
- move(0, 0);
- printw("Invalid filter");
- refresh();
- sleep(1);
- } else {
- strlcpy(f_s, tmp_f_s, sizeof(f_s));
- f_re = tmp_f_re;
- }
- break;
- case 'F':
- f_s[0] = '\0';
- break;
- case 'q':
- quit = 1;
- break;
- default:
+ if (fflush(stdout) == EOF)
break;
+ usleep(flag_I);
+ } else {
+ getyx(stdscr, cury, curx);
+ getmaxyx(stdscr, maxy, maxx);
+ clrtobot();
+ if (maxy - 1 <= cury)
+ move(maxy - 1, 0);
+ refresh();
+
+ int di = flag_I;
+ while (di > 0) {
+ int dii = di;
+ if (dii > 100000)
+ dii = 100000;
+ usleep(dii);
+ di -= dii;
+ if (poll_input())
+ break;
}
}
}
-out:
if (!flag_b) {
el_end(el);
endwin();
}
exit(EX_OK);
}
-
-static void
*** 6 LINES SKIPPED ***