1 1.39 christos /* $NetBSD: iostat.c,v 1.39 2019/01/25 15:31:11 christos Exp $ */ 2 1.2 jtc 3 1.1 jtc /* 4 1.1 jtc * Copyright (c) 1980, 1992, 1993 5 1.1 jtc * The Regents of the University of California. All rights reserved. 6 1.1 jtc * 7 1.1 jtc * Redistribution and use in source and binary forms, with or without 8 1.1 jtc * modification, are permitted provided that the following conditions 9 1.1 jtc * are met: 10 1.1 jtc * 1. Redistributions of source code must retain the above copyright 11 1.1 jtc * notice, this list of conditions and the following disclaimer. 12 1.1 jtc * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jtc * notice, this list of conditions and the following disclaimer in the 14 1.1 jtc * documentation and/or other materials provided with the distribution. 15 1.28 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 jtc * may be used to endorse or promote products derived from this software 17 1.1 jtc * without specific prior written permission. 18 1.1 jtc * 19 1.1 jtc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 jtc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 jtc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 jtc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 jtc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 jtc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 jtc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 jtc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 jtc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 jtc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 jtc * SUCH DAMAGE. 30 1.1 jtc */ 31 1.1 jtc 32 1.8 mrg #include <sys/cdefs.h> 33 1.1 jtc #ifndef lint 34 1.2 jtc #if 0 35 1.1 jtc static char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93"; 36 1.2 jtc #endif 37 1.39 christos __RCSID("$NetBSD: iostat.c,v 1.39 2019/01/25 15:31:11 christos Exp $"); 38 1.18 cgd #endif /* not lint */ 39 1.1 jtc 40 1.1 jtc #include <sys/param.h> 41 1.1 jtc 42 1.1 jtc #include <string.h> 43 1.17 simonb 44 1.1 jtc #include "systat.h" 45 1.1 jtc #include "extern.h" 46 1.36 blymn #include "drvstats.h" 47 1.1 jtc 48 1.1 jtc static int linesperregion; 49 1.1 jtc static int numbers = 0; /* default display bar graphs */ 50 1.5 thorpej static int secs = 0; /* default seconds shown */ 51 1.23 mrg static int read_write = 0; /* default read/write shown */ 52 1.1 jtc 53 1.16 ad static int barlabels(int); 54 1.16 ad static void histogram(double, int, double); 55 1.16 ad static int numlabels(int); 56 1.16 ad static int stats(int, int, int); 57 1.16 ad static void stat1(int, int); 58 1.1 jtc 59 1.1 jtc 60 1.1 jtc WINDOW * 61 1.16 ad openiostat(void) 62 1.1 jtc { 63 1.8 mrg 64 1.27 dsl return (subwin(stdscr, -1, 0, 5, 0)); 65 1.1 jtc } 66 1.1 jtc 67 1.1 jtc void 68 1.16 ad closeiostat(WINDOW *w) 69 1.1 jtc { 70 1.8 mrg 71 1.1 jtc if (w == NULL) 72 1.1 jtc return; 73 1.1 jtc wclear(w); 74 1.1 jtc wrefresh(w); 75 1.1 jtc delwin(w); 76 1.1 jtc } 77 1.1 jtc 78 1.1 jtc int 79 1.16 ad initiostat(void) 80 1.1 jtc { 81 1.8 mrg 82 1.36 blymn drvinit(1); 83 1.34 dsl cpureadstats(); 84 1.36 blymn drvreadstats(); 85 1.8 mrg return(1); 86 1.1 jtc } 87 1.1 jtc 88 1.1 jtc void 89 1.16 ad fetchiostat(void) 90 1.1 jtc { 91 1.8 mrg 92 1.34 dsl cpureadstats(); 93 1.34 dsl 94 1.36 blymn if (ndrive != 0) 95 1.36 blymn drvreadstats(); 96 1.1 jtc } 97 1.1 jtc 98 1.12 mjl #define INSET 14 99 1.1 jtc 100 1.1 jtc void 101 1.16 ad labeliostat(void) 102 1.1 jtc { 103 1.1 jtc int row; 104 1.1 jtc 105 1.36 blymn if (ndrive == 0) { 106 1.5 thorpej error("No drives defined."); 107 1.1 jtc return; 108 1.1 jtc } 109 1.1 jtc row = 0; 110 1.1 jtc wmove(wnd, row, 0); wclrtobot(wnd); 111 1.1 jtc mvwaddstr(wnd, row++, INSET, 112 1.1 jtc "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); 113 1.30 wiz mvwaddstr(wnd, row++, 0, " CPU user|"); 114 1.12 mjl mvwaddstr(wnd, row++, 0, " nice|"); 115 1.12 mjl mvwaddstr(wnd, row++, 0, " system|"); 116 1.12 mjl mvwaddstr(wnd, row++, 0, " interrupt|"); 117 1.12 mjl mvwaddstr(wnd, row++, 0, " idle|"); 118 1.1 jtc if (numbers) 119 1.1 jtc row = numlabels(row + 1); 120 1.1 jtc else 121 1.1 jtc row = barlabels(row + 1); 122 1.1 jtc } 123 1.1 jtc 124 1.1 jtc static int 125 1.16 ad numlabels(int row) 126 1.1 jtc { 127 1.37 lukem int col, regions; 128 1.37 lukem size_t i, ndrives; 129 1.1 jtc 130 1.32 dsl #define COLWIDTH (9 + secs * 5 + 1 + read_write * 9 + 1) 131 1.29 dsl #define DRIVESPERLINE ((getmaxx(wnd) + 1) / COLWIDTH) 132 1.36 blymn for (ndrives = 0, i = 0; i < ndrive; i++) 133 1.36 blymn if (cur.select[i]) 134 1.1 jtc ndrives++; 135 1.36 blymn 136 1.1 jtc regions = howmany(ndrives, DRIVESPERLINE); 137 1.1 jtc /* 138 1.1 jtc * Deduct -regions for blank line after each scrolling region. 139 1.1 jtc */ 140 1.29 dsl linesperregion = (getmaxy(wnd) - row - regions + 1) / regions; 141 1.1 jtc /* 142 1.1 jtc * Minimum region contains space for two 143 1.1 jtc * label lines and one line of statistics. 144 1.1 jtc */ 145 1.1 jtc if (linesperregion < 3) 146 1.1 jtc linesperregion = 3; 147 1.1 jtc col = 0; 148 1.36 blymn for (i = 0; i < ndrive; i++) 149 1.36 blymn if (cur.select[i]) { 150 1.29 dsl if (col + COLWIDTH - 1 > getmaxx(wnd)) { 151 1.1 jtc col = 0, row += linesperregion + 1; 152 1.29 dsl if (row > getmaxy(wnd) - (linesperregion)) 153 1.1 jtc break; 154 1.1 jtc } 155 1.33 blymn 156 1.36 blymn mvwprintw(wnd, row, col + 5, "%s", cur.name[i]); 157 1.36 blymn 158 1.23 mrg if (read_write) 159 1.32 dsl mvwprintw(wnd, row, col + 11 + secs * 5, 160 1.31 dsl "(write)"); 161 1.32 dsl mvwprintw(wnd, row + 1, col, " kBps %s", 162 1.31 dsl read_write ? "r/s" : "tps"); 163 1.31 dsl if (secs) 164 1.31 dsl waddstr(wnd, " sec"); 165 1.31 dsl if (read_write) 166 1.32 dsl waddstr(wnd, " kBps w/s"); 167 1.1 jtc col += COLWIDTH; 168 1.1 jtc } 169 1.1 jtc if (col) 170 1.1 jtc row += linesperregion + 1; 171 1.1 jtc return (row); 172 1.1 jtc } 173 1.1 jtc 174 1.1 jtc static int 175 1.16 ad barlabels(int row) 176 1.1 jtc { 177 1.37 lukem size_t i; 178 1.1 jtc 179 1.1 jtc mvwaddstr(wnd, row++, INSET, 180 1.5 thorpej "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); 181 1.23 mrg linesperregion = 2 + secs + (read_write ? 2 : 0); 182 1.36 blymn for (i = 0; i < ndrive; i++) { 183 1.36 blymn if (cur.select[i]) { 184 1.7 jtc if (row > getmaxy(wnd) - linesperregion) 185 1.1 jtc break; 186 1.24 thorpej mvwprintw(wnd, row++, 0, "%7.7s kBps|", 187 1.36 blymn cur.name[i]); 188 1.33 blymn mvwaddstr(wnd, row++, 0, " tps|"); 189 1.33 blymn if (read_write) { 190 1.33 blymn mvwprintw(wnd, row++, 0, " (write) kBps|"); 191 1.33 blymn mvwaddstr(wnd, row++, 0, " tps|"); 192 1.33 blymn } 193 1.33 blymn if (secs) 194 1.33 blymn mvwaddstr(wnd, row++, 0, " msec|"); 195 1.33 blymn } 196 1.36 blymn } 197 1.36 blymn 198 1.1 jtc return (row); 199 1.1 jtc } 200 1.1 jtc 201 1.1 jtc void 202 1.16 ad showiostat(void) 203 1.1 jtc { 204 1.37 lukem int row, col; 205 1.37 lukem size_t i; 206 1.1 jtc 207 1.36 blymn if (ndrive == 0) 208 1.1 jtc return; 209 1.34 dsl cpuswap(); 210 1.36 blymn drvswap(); 211 1.5 thorpej 212 1.21 sommerfe etime = cur.cp_etime; 213 1.1 jtc row = 1; 214 1.1 jtc 215 1.1 jtc /* 216 1.3 mycroft * Interrupt CPU state not calculated yet. 217 1.21 sommerfe */ 218 1.3 mycroft for (i = 0; i < CPUSTATES; i++) 219 1.1 jtc stat1(row++, i); 220 1.1 jtc if (!numbers) { 221 1.1 jtc row += 2; 222 1.36 blymn for (i = 0; i < ndrive; i++) 223 1.36 blymn if (cur.select[i]) { 224 1.7 jtc if (row > getmaxy(wnd) - linesperregion) 225 1.1 jtc break; 226 1.1 jtc row = stats(row, INSET, i); 227 1.1 jtc } 228 1.1 jtc return; 229 1.1 jtc } 230 1.1 jtc col = 0; 231 1.1 jtc wmove(wnd, row + linesperregion, 0); 232 1.1 jtc wdeleteln(wnd); 233 1.1 jtc wmove(wnd, row + 3, 0); 234 1.1 jtc winsertln(wnd); 235 1.36 blymn for (i = 0; i < ndrive; i++) 236 1.36 blymn if (cur.select[i]) { 237 1.33 blymn if (col + COLWIDTH - 1 > getmaxx(wnd)) { 238 1.33 blymn col = 0, row += linesperregion + 1; 239 1.33 blymn if (row > getmaxy(wnd) - (linesperregion + 1)) 240 1.33 blymn break; 241 1.33 blymn wmove(wnd, row + linesperregion, 0); 242 1.33 blymn wdeleteln(wnd); 243 1.33 blymn wmove(wnd, row + 3, 0); 244 1.33 blymn winsertln(wnd); 245 1.33 blymn } 246 1.33 blymn (void) stats(row + 3, col, i); 247 1.33 blymn col += COLWIDTH; 248 1.33 blymn } 249 1.1 jtc } 250 1.1 jtc 251 1.1 jtc static int 252 1.16 ad stats(int row, int col, int dn) 253 1.1 jtc { 254 1.38 mlelstv double atime, dtime, rwords, wwords; 255 1.31 dsl uint64_t rxfer; 256 1.5 thorpej 257 1.38 mlelstv /* elapsed time for disk stats */ 258 1.38 mlelstv dtime = etime; 259 1.38 mlelstv if (cur.timestamp[dn].tv_sec || cur.timestamp[dn].tv_usec) 260 1.38 mlelstv dtime = (double)cur.timestamp[dn].tv_sec + 261 1.38 mlelstv ((double)cur.timestamp[dn].tv_usec / (double)1000000); 262 1.38 mlelstv 263 1.5 thorpej /* time busy in disk activity */ 264 1.36 blymn atime = (double)cur.time[dn].tv_sec + 265 1.36 blymn ((double)cur.time[dn].tv_usec / (double)1000000); 266 1.1 jtc 267 1.23 mrg /* # of k transferred */ 268 1.36 blymn rwords = cur.rbytes[dn] / 1024.0; 269 1.36 blymn wwords = cur.wbytes[dn] / 1024.0; 270 1.36 blymn rxfer = cur.rxfer[dn]; 271 1.31 dsl if (!read_write) { 272 1.35 dsl rwords += wwords; 273 1.36 blymn rxfer += cur.wxfer[dn]; 274 1.33 blymn } 275 1.33 blymn if (numbers) { 276 1.33 blymn mvwprintw(wnd, row, col, "%5.0f%4.0f", 277 1.38 mlelstv rwords / dtime, rxfer / dtime); 278 1.33 blymn if (secs) 279 1.38 mlelstv wprintw(wnd, "%5.1f", atime / dtime); 280 1.33 blymn if (read_write) 281 1.33 blymn wprintw(wnd, " %5.0f%4.0f", 282 1.38 mlelstv wwords / dtime, cur.wxfer[dn] / dtime); 283 1.33 blymn return (row); 284 1.33 blymn } 285 1.33 blymn 286 1.33 blymn wmove(wnd, row++, col); 287 1.38 mlelstv histogram(rwords / dtime, 50, 0.5); 288 1.33 blymn wmove(wnd, row++, col); 289 1.38 mlelstv histogram(rxfer / dtime, 50, 0.5); 290 1.33 blymn if (read_write) { 291 1.33 blymn wmove(wnd, row++, col); 292 1.38 mlelstv histogram(wwords / dtime, 50, 0.5); 293 1.33 blymn wmove(wnd, row++, col); 294 1.38 mlelstv histogram(cur.wxfer[dn] / dtime, 50, 0.5); 295 1.33 blymn } 296 1.33 blymn 297 1.33 blymn if (secs) { 298 1.33 blymn wmove(wnd, row++, col); 299 1.33 blymn atime *= 1000; /* In milliseconds */ 300 1.38 mlelstv histogram(atime / dtime, 50, 0.5); 301 1.33 blymn } 302 1.33 blymn return (row); 303 1.33 blymn } 304 1.33 blymn 305 1.1 jtc static void 306 1.16 ad stat1(int row, int o) 307 1.1 jtc { 308 1.37 lukem size_t i; 309 1.31 dsl double total_time; 310 1.1 jtc 311 1.31 dsl total_time = 0; 312 1.1 jtc for (i = 0; i < CPUSTATES; i++) 313 1.31 dsl total_time += cur.cp_time[i]; 314 1.31 dsl if (total_time == 0.0) 315 1.31 dsl total_time = 1.0; 316 1.1 jtc wmove(wnd, row, INSET); 317 1.1 jtc #define CPUSCALE 0.5 318 1.31 dsl histogram(100.0 * cur.cp_time[o] / total_time, 50, CPUSCALE); 319 1.1 jtc } 320 1.1 jtc 321 1.1 jtc static void 322 1.16 ad histogram(double val, int colwidth, double scale) 323 1.1 jtc { 324 1.26 dsl int v = (int)(val * scale + 0.5); 325 1.26 dsl int factor = 1; 326 1.26 dsl int y, x; 327 1.26 dsl 328 1.26 dsl while (v > colwidth) { 329 1.26 dsl v = (v + 5) / 10; 330 1.26 dsl factor *= 10; 331 1.1 jtc } 332 1.26 dsl getyx(wnd, y, x); 333 1.1 jtc wclrtoeol(wnd); 334 1.26 dsl whline(wnd, 'X', v); 335 1.26 dsl if (factor != 1) 336 1.26 dsl mvwprintw(wnd, y, x + colwidth + 1, "* %d ", factor); 337 1.1 jtc } 338 1.1 jtc 339 1.13 jwise void 340 1.16 ad iostat_bars(char *args) 341 1.13 jwise { 342 1.13 jwise numbers = 0; 343 1.13 jwise wclear(wnd); 344 1.13 jwise labeliostat(); 345 1.13 jwise refresh(); 346 1.13 jwise } 347 1.13 jwise 348 1.13 jwise void 349 1.16 ad iostat_numbers(char *args) 350 1.1 jtc { 351 1.13 jwise numbers = 1; 352 1.13 jwise wclear(wnd); 353 1.13 jwise labeliostat(); 354 1.13 jwise refresh(); 355 1.13 jwise } 356 1.1 jtc 357 1.13 jwise void 358 1.16 ad iostat_secs(char *args) 359 1.13 jwise { 360 1.13 jwise secs = !secs; 361 1.23 mrg wclear(wnd); 362 1.23 mrg labeliostat(); 363 1.23 mrg refresh(); 364 1.23 mrg } 365 1.23 mrg 366 1.23 mrg void 367 1.23 mrg iostat_rw(char *args) 368 1.23 mrg { 369 1.31 dsl read_write ^= 1; 370 1.23 mrg wclear(wnd); 371 1.23 mrg labeliostat(); 372 1.23 mrg refresh(); 373 1.23 mrg } 374 1.23 mrg 375 1.23 mrg void 376 1.23 mrg iostat_all(char *args) 377 1.23 mrg { 378 1.23 mrg read_write = 0; 379 1.1 jtc wclear(wnd); 380 1.1 jtc labeliostat(); 381 1.1 jtc refresh(); 382 1.1 jtc } 383