1 /*- 2 * Copyright (c) 2003 Poul-Henning Kamp 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The names of the authors may not be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 33 #include <stdio.h> 34 #include <stdint.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <paths.h> 38 #include <curses.h> 39 #include <unistd.h> 40 #include <fcntl.h> 41 #include <errno.h> 42 #include <err.h> 43 #include <sys/mman.h> 44 #include <sys/time.h> 45 #include <libgeom.h> 46 #include <sys/resource.h> 47 #include <devstat.h> 48 #include <sys/devicestat.h> 49 50 static int flag_c; 51 static int flag_I = 500000; 52 53 static void usage(void); 54 55 int 56 main(int argc, char **argv) 57 { 58 int error, i, quit; 59 struct devstat *gsp, *gsq; 60 void *sp, *sq; 61 double dt; 62 struct timespec tp, tq; 63 struct gmesh gmp; 64 struct gprovider *pp; 65 struct gconsumer *cp;; 66 struct gident *gid; 67 short cf, cb; 68 char *p; 69 long double ld[8]; 70 uint64_t u64; 71 72 while ((i = getopt(argc, argv, "cI:")) != -1) { 73 switch (i) { 74 case 'c': 75 flag_c = 1; 76 break; 77 case 'I': 78 p = NULL; 79 i = strtoul(optarg, &p, 0); 80 if (p == optarg || errno == EINVAL || 81 errno == ERANGE) { 82 errx(1, "Invalid argument to -I"); 83 } else if (!strcmp(p, "s")) 84 i *= 1000000; 85 else if (!strcmp(p, "ms")) 86 i *= 1000; 87 else if (!strcmp(p, "us")) 88 i *= 1; 89 flag_I = i; 90 break; 91 case '?': 92 default: 93 usage(); 94 } 95 } 96 argc -= optind; 97 argv += optind; 98 if (argc != 0) 99 usage(); 100 101 i = geom_gettree(&gmp); 102 if (i != 0) 103 err(1, "geom_gettree = %d", i); 104 error = geom_stats_open(); 105 if (error) 106 err(1, "geom_stats_open()"); 107 sq = NULL; 108 sq = geom_stats_snapshot_get(); 109 if (sq == NULL) 110 err(1, "geom_stats_snapshot()"); 111 initscr(); 112 start_color(); 113 use_default_colors(); 114 pair_content(0, &cf, &cb); 115 init_pair(1, COLOR_GREEN, cb); 116 init_pair(2, COLOR_MAGENTA, cb); 117 init_pair(3, COLOR_RED, cb); 118 cbreak(); 119 noecho(); 120 nonl(); 121 nodelay(stdscr, 1); 122 intrflush(stdscr, FALSE); 123 keypad(stdscr, TRUE); 124 geom_stats_snapshot_timestamp(sq, &tq); 125 for (quit = 0; !quit;) { 126 sp = geom_stats_snapshot_get(); 127 if (sp == NULL) 128 err(1, "geom_stats_snapshot()"); 129 geom_stats_snapshot_timestamp(sp, &tp); 130 dt = tp.tv_sec - tq.tv_sec; 131 dt += (tp.tv_nsec - tq.tv_nsec) * 1e-9; 132 tq = tp; 133 134 geom_stats_snapshot_reset(sp); 135 geom_stats_snapshot_reset(sq); 136 move(0,0); 137 printw("dT: %5.3f flag_I %dus sizeof %d i %d\n", 138 dt, flag_I, sizeof(*gsp), i); 139 printw(" L(q) ops/s r/s kBps ms/r w/s kBps ms/w %%busy Name\n"); 140 for (;;) { 141 gsp = geom_stats_snapshot_next(sp); 142 gsq = geom_stats_snapshot_next(sq); 143 if (gsp == NULL || gsq == NULL) 144 break; 145 if (gsp->id == NULL) 146 continue; 147 gid = geom_lookupid(&gmp, gsp->id); 148 if (gid == NULL) { 149 geom_deletetree(&gmp); 150 i = geom_gettree(&gmp); 151 if (i != 0) 152 err(1, "geom_gettree = %d", i); 153 gid = geom_lookupid(&gmp, gsp->id); 154 } 155 if (gid == NULL) 156 continue; 157 if (gid != NULL && gid->what == ISCONSUMER && !flag_c) 158 continue; 159 if (gsp->sequence0 != gsp->sequence1) { 160 printw("*\n"); 161 continue; 162 } 163 devstat_compute_statistics(gsp, gsq, dt, 164 DSM_QUEUE_LENGTH, &u64, 165 DSM_TRANSFERS_PER_SECOND, &ld[0], 166 DSM_TRANSFERS_PER_SECOND_READ, &ld[1], 167 DSM_MB_PER_SECOND_READ, &ld[2], 168 DSM_MS_PER_TRANSACTION_READ, &ld[3], 169 DSM_TRANSFERS_PER_SECOND_WRITE, &ld[4], 170 DSM_MB_PER_SECOND_WRITE, &ld[5], 171 DSM_MS_PER_TRANSACTION_WRITE, &ld[6], 172 DSM_BUSY_PCT, &ld[7], 173 DSM_NONE); 174 175 printw(" %4ju", (uintmax_t)u64); 176 printw(" %6.0f", (double)ld[0]); 177 printw(" %6.0f", (double)ld[1]); 178 printw(" %6.0f", (double)ld[2] * 1024); 179 printw(" %6.1f", (double)ld[3]); 180 printw(" %6.0f", (double)ld[4]); 181 printw(" %6.0f", (double)ld[5] * 1024); 182 printw(" %6.1f", (double)ld[6]); 183 184 if (ld[7] > 80) 185 i = 3; 186 else if (ld[7] > 50) 187 i = 2; 188 else 189 i = 1; 190 attron(COLOR_PAIR(i)); 191 printw(" %6.1lf", (double)ld[7]); 192 attroff(COLOR_PAIR(i)); 193 printw("|"); 194 if (gid == NULL) { 195 printw(" ??"); 196 } else if (gid->what == ISPROVIDER) { 197 pp = gid->ptr; 198 printw(" %s", pp->name); 199 } else if (gid->what == ISCONSUMER) { 200 cp = gid->ptr; 201 printw(" %s/%s/%s", 202 cp->geom->class->name, 203 cp->geom->name, 204 cp->provider->name); 205 } 206 clrtoeol(); 207 printw("\n"); 208 *gsq = *gsp; 209 } 210 geom_stats_snapshot_free(sp); 211 clrtobot(); 212 refresh(); 213 usleep(flag_I); 214 i = getch(); 215 switch (i) { 216 case '>': 217 flag_I *= 2; 218 break; 219 case '<': 220 flag_I /= 2; 221 if (flag_I < 1000) 222 flag_I = 1000; 223 break; 224 case 'c': 225 flag_c = !flag_c; 226 break; 227 case 'q': 228 quit = 1; 229 break; 230 default: 231 break; 232 } 233 } 234 235 endwin(); 236 exit (0); 237 } 238 239 static void 240 usage(void) 241 { 242 fprintf(stderr, "usage: gstat [-c] [-I interval]\n"); 243 exit(1); 244 /* NOTREACHED */ 245 } 246