summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2003-03-20 20:48:41 +0000
committerphk <phk@FreeBSD.org>2003-03-20 20:48:41 +0000
commitf3139ecc8bc1ddda28bad45788ac096a921bc913 (patch)
tree5c6dbf9c6246e7dbbac1b891d9a8e3f55ce94d9e
parentad2b755e2794102f8095adeff6f6f028dec3211f (diff)
downloadFreeBSD-src-f3139ecc8bc1ddda28bad45788ac096a921bc913.zip
FreeBSD-src-f3139ecc8bc1ddda28bad45788ac096a921bc913.tar.gz
Add a rudimentary gstat(8) to the system.
This is a small curses based program which shows the diskactivity inside GEOM.
-rw-r--r--usr.sbin/Makefile1
-rw-r--r--usr.sbin/gstat/Makefile19
-rw-r--r--usr.sbin/gstat/gstat.c232
3 files changed, 252 insertions, 0 deletions
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index 7d9e4b1..b0fc31f 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -40,6 +40,7 @@ SUBDIR= IPXrouted \
fwcontrol \
getfmac \
getpmac \
+ gstat \
ifmcstat \
inetd \
iostat \
diff --git a/usr.sbin/gstat/Makefile b/usr.sbin/gstat/Makefile
new file mode 100644
index 0000000..f7ef534
--- /dev/null
+++ b/usr.sbin/gstat/Makefile
@@ -0,0 +1,19 @@
+# $FreeBSD$
+
+PROG= gstat
+
+SRCS= gstat.c subr_sbuf.c
+
+.PATH: ${CURDIR}/../../../../sys/kern
+
+WARNS?= 5
+
+LDADD += -lgeom
+LDADD += -ldevstat
+LDADD += -lkvm
+LDADD += -lbsdxml
+LDADD += -lcurses
+
+NOMAN= sorry
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/gstat/gstat.c b/usr.sbin/gstat/gstat.c
new file mode 100644
index 0000000..6d3a698
--- /dev/null
+++ b/usr.sbin/gstat/gstat.c
@@ -0,0 +1,232 @@
+/*-
+ * Copyright (c) 2003 Poul-Henning Kamp
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include <curses.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <err.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <libgeom.h>
+#include <sys/resource.h>
+#include <devstat.h>
+#include <sys/devicestat.h>
+
+static int flag_c;
+static int flag_I = 500000;
+
+int
+main(int argc, char **argv)
+{
+ int error, i, quit;
+ 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;
+ short cf, cb;
+ char *p;
+ long double ld[8];
+ uint64_t u64;
+
+ while ((i = getopt(argc, argv, "cI:")) != -1) {
+ switch (i) {
+ case 'c':
+ flag_c = !flag_c;
+ break;
+ case 'I':
+ p = NULL;
+ i = strtoul(optarg, &p, 0);
+ if (p == optarg) {
+ errx(1, "Invalid argument to -I");
+ } else if (!strcmp(p, "s"))
+ i *= 1000000;
+ else if (!strcmp(p, "ms"))
+ i *= 1000;
+ else if (!strcmp(p, "us"))
+ i *= 1;
+ flag_I = i;
+ break;
+ case '?':
+ default:
+ errx(1, "Usage!");
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc != 0)
+ errx(1, "Usage!");
+
+ i = geom_gettree(&gmp);
+ if (i != 0)
+ err(1, "geom_gettree = %d", i);
+ 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()");
+ 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);
+ geom_stats_snapshot_timestamp(sq, &tq);
+ for (quit = 0; !quit;) {
+ sp = geom_stats_snapshot_get();
+ if (sp == NULL)
+ err(1, "geom_stats_snapshot()");
+ geom_stats_snapshot_timestamp(sp, &tp);
+ dt = tp.tv_sec - tq.tv_sec;
+ dt += (tp.tv_nsec - tq.tv_nsec) * 1e-9;
+ tq = tp;
+
+ geom_stats_snapshot_reset(sp);
+ geom_stats_snapshot_reset(sq);
+ move(0,0);
+ printw("dT: %5.3f flag_I %dus sizeof %d i %d\n",
+ dt, flag_I, sizeof(*gsp), i);
+ printw(" L(q) ops/s r/s kBps ms/r w/s kBps ms/w %%busy Name\n");
+ for (;;) {
+ gsp = geom_stats_snapshot_next(sp);
+ gsq = geom_stats_snapshot_next(sq);
+ if (gsp == NULL || gsq == NULL)
+ break;
+ if (gsp->id == NULL)
+ continue;
+ gid = geom_lookupid(&gmp, gsp->id);
+ if (gid == NULL) {
+ geom_deletetree(&gmp);
+ i = geom_gettree(&gmp);
+ if (i != 0)
+ err(1, "geom_gettree = %d", i);
+ gid = geom_lookupid(&gmp, gsp->id);
+ }
+ if (gid == NULL)
+ continue;
+ if (gid != NULL && gid->what == ISCONSUMER && !flag_c)
+ continue;
+ if (gsp->sequence0 != gsp->sequence1) {
+ printw("*\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],
+ DSM_BUSY_PCT, &ld[7],
+ DSM_NONE);
+
+ printw(" %4ju", (uintmax_t)u64);
+ printw(" %6.0f", (double)ld[0]);
+ printw(" %6.0f", (double)ld[1]);
+ printw(" %6.0f", (double)ld[2] * 1024);
+ printw(" %6.1f", (double)ld[3]);
+ printw(" %6.0f", (double)ld[4]);
+ printw(" %6.0f", (double)ld[5] * 1024);
+ printw(" %6.1f", (double)ld[6]);
+
+ if (ld[7] > 80)
+ i = 3;
+ else if (ld[7] > 50)
+ i = 2;
+ else
+ i = 1;
+ attron(COLOR_PAIR(i));
+ printw(" %6.1lf", (double)ld[7]);
+ attroff(COLOR_PAIR(i));
+ printw("|");
+ if (gid == NULL) {
+ printw(" ??");
+ } else if (gid->what == ISPROVIDER) {
+ pp = gid->ptr;
+ printw(" %s", pp->name);
+ } else if (gid->what == ISCONSUMER) {
+ cp = gid->ptr;
+ printw(" %s/%s/%s",
+ cp->geom->class->name,
+ cp->geom->name,
+ cp->provider->name);
+ }
+ clrtoeol();
+ printw("\n");
+ *gsq = *gsp;
+ }
+ geom_stats_snapshot_free(sp);
+ clrtobot();
+ refresh();
+ usleep(flag_I);
+ i = getch();
+ 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 'q':
+ quit = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ exit (0);
+}
OpenPOWER on IntegriCloud