1*6b2ce080Schristos /* $NetBSD: iostat.c,v 1.39 2019/01/25 15:31:11 christos Exp $ */
22f3cb7aeSjtc
312749a2aSjtc /*
412749a2aSjtc * Copyright (c) 1980, 1992, 1993
512749a2aSjtc * The Regents of the University of California. All rights reserved.
612749a2aSjtc *
712749a2aSjtc * Redistribution and use in source and binary forms, with or without
812749a2aSjtc * modification, are permitted provided that the following conditions
912749a2aSjtc * are met:
1012749a2aSjtc * 1. Redistributions of source code must retain the above copyright
1112749a2aSjtc * notice, this list of conditions and the following disclaimer.
1212749a2aSjtc * 2. Redistributions in binary form must reproduce the above copyright
1312749a2aSjtc * notice, this list of conditions and the following disclaimer in the
1412749a2aSjtc * documentation and/or other materials provided with the distribution.
1589aaa1bbSagc * 3. Neither the name of the University nor the names of its contributors
1612749a2aSjtc * may be used to endorse or promote products derived from this software
1712749a2aSjtc * without specific prior written permission.
1812749a2aSjtc *
1912749a2aSjtc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2012749a2aSjtc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2112749a2aSjtc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2212749a2aSjtc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2312749a2aSjtc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2412749a2aSjtc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2512749a2aSjtc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2612749a2aSjtc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2712749a2aSjtc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2812749a2aSjtc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2912749a2aSjtc * SUCH DAMAGE.
3012749a2aSjtc */
3112749a2aSjtc
3259413993Smrg #include <sys/cdefs.h>
3312749a2aSjtc #ifndef lint
342f3cb7aeSjtc #if 0
3512749a2aSjtc static char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93";
362f3cb7aeSjtc #endif
37*6b2ce080Schristos __RCSID("$NetBSD: iostat.c,v 1.39 2019/01/25 15:31:11 christos Exp $");
38d594ce93Scgd #endif /* not lint */
3912749a2aSjtc
4012749a2aSjtc #include <sys/param.h>
4112749a2aSjtc
4212749a2aSjtc #include <string.h>
43828483a7Ssimonb
4412749a2aSjtc #include "systat.h"
4512749a2aSjtc #include "extern.h"
46e48af18bSblymn #include "drvstats.h"
4712749a2aSjtc
4812749a2aSjtc static int linesperregion;
4912749a2aSjtc static int numbers = 0; /* default display bar graphs */
501eaf5ee3Sthorpej static int secs = 0; /* default seconds shown */
513cf4c73dSmrg static int read_write = 0; /* default read/write shown */
5212749a2aSjtc
53fc391547Sad static int barlabels(int);
54fc391547Sad static void histogram(double, int, double);
55fc391547Sad static int numlabels(int);
56fc391547Sad static int stats(int, int, int);
57fc391547Sad static void stat1(int, int);
5812749a2aSjtc
5912749a2aSjtc
6012749a2aSjtc WINDOW *
openiostat(void)61fc391547Sad openiostat(void)
6212749a2aSjtc {
6359413993Smrg
649f46bb07Sdsl return (subwin(stdscr, -1, 0, 5, 0));
6512749a2aSjtc }
6612749a2aSjtc
6712749a2aSjtc void
closeiostat(WINDOW * w)68fc391547Sad closeiostat(WINDOW *w)
6912749a2aSjtc {
7059413993Smrg
7112749a2aSjtc if (w == NULL)
7212749a2aSjtc return;
7312749a2aSjtc wclear(w);
7412749a2aSjtc wrefresh(w);
7512749a2aSjtc delwin(w);
7612749a2aSjtc }
7712749a2aSjtc
7812749a2aSjtc int
initiostat(void)79fc391547Sad initiostat(void)
8012749a2aSjtc {
8159413993Smrg
82e48af18bSblymn drvinit(1);
830283f983Sdsl cpureadstats();
84e48af18bSblymn drvreadstats();
8559413993Smrg return(1);
8612749a2aSjtc }
8712749a2aSjtc
8812749a2aSjtc void
fetchiostat(void)89fc391547Sad fetchiostat(void)
9012749a2aSjtc {
9159413993Smrg
920283f983Sdsl cpureadstats();
930283f983Sdsl
94e48af18bSblymn if (ndrive != 0)
95e48af18bSblymn drvreadstats();
9612749a2aSjtc }
9712749a2aSjtc
98d278ba38Smjl #define INSET 14
9912749a2aSjtc
10012749a2aSjtc void
labeliostat(void)101fc391547Sad labeliostat(void)
10212749a2aSjtc {
10312749a2aSjtc int row;
10412749a2aSjtc
105e48af18bSblymn if (ndrive == 0) {
1061eaf5ee3Sthorpej error("No drives defined.");
10712749a2aSjtc return;
10812749a2aSjtc }
10912749a2aSjtc row = 0;
11012749a2aSjtc wmove(wnd, row, 0); wclrtobot(wnd);
11112749a2aSjtc mvwaddstr(wnd, row++, INSET,
11212749a2aSjtc "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
113d20841bbSwiz mvwaddstr(wnd, row++, 0, " CPU user|");
11412749a2aSjtc mvwaddstr(wnd, row++, 0, " nice|");
11512749a2aSjtc mvwaddstr(wnd, row++, 0, " system|");
11664806926Smycroft mvwaddstr(wnd, row++, 0, " interrupt|");
11712749a2aSjtc mvwaddstr(wnd, row++, 0, " idle|");
11812749a2aSjtc if (numbers)
11912749a2aSjtc row = numlabels(row + 1);
12012749a2aSjtc else
12112749a2aSjtc row = barlabels(row + 1);
12212749a2aSjtc }
12312749a2aSjtc
12412749a2aSjtc static int
numlabels(int row)125fc391547Sad numlabels(int row)
12612749a2aSjtc {
127e7a39c4fSlukem int col, regions;
128e7a39c4fSlukem size_t i, ndrives;
12912749a2aSjtc
130f62ff76fSdsl #define COLWIDTH (9 + secs * 5 + 1 + read_write * 9 + 1)
13155a20c51Sdsl #define DRIVESPERLINE ((getmaxx(wnd) + 1) / COLWIDTH)
132e48af18bSblymn for (ndrives = 0, i = 0; i < ndrive; i++)
133e48af18bSblymn if (cur.select[i])
134132bb1feSblymn ndrives++;
135132bb1feSblymn
13612749a2aSjtc regions = howmany(ndrives, DRIVESPERLINE);
13712749a2aSjtc /*
13812749a2aSjtc * Deduct -regions for blank line after each scrolling region.
13912749a2aSjtc */
14055a20c51Sdsl linesperregion = (getmaxy(wnd) - row - regions + 1) / regions;
14112749a2aSjtc /*
14212749a2aSjtc * Minimum region contains space for two
14312749a2aSjtc * label lines and one line of statistics.
14412749a2aSjtc */
14512749a2aSjtc if (linesperregion < 3)
14612749a2aSjtc linesperregion = 3;
14712749a2aSjtc col = 0;
148e48af18bSblymn for (i = 0; i < ndrive; i++)
149e48af18bSblymn if (cur.select[i]) {
15055a20c51Sdsl if (col + COLWIDTH - 1 > getmaxx(wnd)) {
15112749a2aSjtc col = 0, row += linesperregion + 1;
15255a20c51Sdsl if (row > getmaxy(wnd) - (linesperregion))
15312749a2aSjtc break;
15412749a2aSjtc }
155132bb1feSblymn
156e48af18bSblymn mvwprintw(wnd, row, col + 5, "%s", cur.name[i]);
157132bb1feSblymn
1583cf4c73dSmrg if (read_write)
159f62ff76fSdsl mvwprintw(wnd, row, col + 11 + secs * 5,
160ff927e70Sdsl "(write)");
161ff927e70Sdsl mvwprintw(wnd, row + 1, col, " kBps %s",
162ff927e70Sdsl read_write ? "r/s" : "tps");
163ff927e70Sdsl if (secs)
164ff927e70Sdsl waddstr(wnd, " sec");
165ff927e70Sdsl if (read_write)
166ff927e70Sdsl waddstr(wnd, " kBps w/s");
16712749a2aSjtc col += COLWIDTH;
16812749a2aSjtc }
16912749a2aSjtc if (col)
17012749a2aSjtc row += linesperregion + 1;
17112749a2aSjtc return (row);
17212749a2aSjtc }
17312749a2aSjtc
17412749a2aSjtc static int
barlabels(int row)175fc391547Sad barlabels(int row)
17612749a2aSjtc {
177e7a39c4fSlukem size_t i;
17812749a2aSjtc
17912749a2aSjtc mvwaddstr(wnd, row++, INSET,
1801eaf5ee3Sthorpej "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
1813cf4c73dSmrg linesperregion = 2 + secs + (read_write ? 2 : 0);
182e48af18bSblymn for (i = 0; i < ndrive; i++) {
183e48af18bSblymn if (cur.select[i]) {
1848fd3f56fSjtc if (row > getmaxy(wnd) - linesperregion)
18512749a2aSjtc break;
1869f3eaa50Sthorpej mvwprintw(wnd, row++, 0, "%7.7s kBps|",
187e48af18bSblymn cur.name[i]);
18812749a2aSjtc mvwaddstr(wnd, row++, 0, " tps|");
1893cf4c73dSmrg if (read_write) {
1903cf4c73dSmrg mvwprintw(wnd, row++, 0, " (write) kBps|");
1913cf4c73dSmrg mvwaddstr(wnd, row++, 0, " tps|");
1923cf4c73dSmrg }
1931eaf5ee3Sthorpej if (secs)
1941eaf5ee3Sthorpej mvwaddstr(wnd, row++, 0, " msec|");
19512749a2aSjtc }
196132bb1feSblymn }
197e48af18bSblymn
19812749a2aSjtc return (row);
19912749a2aSjtc }
20012749a2aSjtc
20112749a2aSjtc void
showiostat(void)202fc391547Sad showiostat(void)
20312749a2aSjtc {
204e7a39c4fSlukem int row, col;
205e7a39c4fSlukem size_t i;
20612749a2aSjtc
207e48af18bSblymn if (ndrive == 0)
20812749a2aSjtc return;
2090283f983Sdsl cpuswap();
210e48af18bSblymn drvswap();
2111eaf5ee3Sthorpej
212f80c7eebSsommerfeld etime = cur.cp_etime;
21312749a2aSjtc row = 1;
21412749a2aSjtc
21512749a2aSjtc /*
21664806926Smycroft * Interrupt CPU state not calculated yet.
21712749a2aSjtc */
21864806926Smycroft for (i = 0; i < CPUSTATES; i++)
21912749a2aSjtc stat1(row++, i);
22012749a2aSjtc if (!numbers) {
22112749a2aSjtc row += 2;
222e48af18bSblymn for (i = 0; i < ndrive; i++)
223e48af18bSblymn if (cur.select[i]) {
2248fd3f56fSjtc if (row > getmaxy(wnd) - linesperregion)
22512749a2aSjtc break;
22612749a2aSjtc row = stats(row, INSET, i);
22712749a2aSjtc }
22812749a2aSjtc return;
22912749a2aSjtc }
23012749a2aSjtc col = 0;
23112749a2aSjtc wmove(wnd, row + linesperregion, 0);
23212749a2aSjtc wdeleteln(wnd);
23312749a2aSjtc wmove(wnd, row + 3, 0);
23412749a2aSjtc winsertln(wnd);
235e48af18bSblymn for (i = 0; i < ndrive; i++)
236e48af18bSblymn if (cur.select[i]) {
237132bb1feSblymn if (col + COLWIDTH - 1 > getmaxx(wnd)) {
238132bb1feSblymn col = 0, row += linesperregion + 1;
239132bb1feSblymn if (row > getmaxy(wnd) - (linesperregion + 1))
240132bb1feSblymn break;
241132bb1feSblymn wmove(wnd, row + linesperregion, 0);
242132bb1feSblymn wdeleteln(wnd);
243132bb1feSblymn wmove(wnd, row + 3, 0);
244132bb1feSblymn winsertln(wnd);
245132bb1feSblymn }
246132bb1feSblymn (void) stats(row + 3, col, i);
247132bb1feSblymn col += COLWIDTH;
248132bb1feSblymn }
24912749a2aSjtc }
25012749a2aSjtc
25112749a2aSjtc static int
stats(int row,int col,int dn)252fc391547Sad stats(int row, int col, int dn)
25312749a2aSjtc {
2549368f38eSmlelstv double atime, dtime, rwords, wwords;
255ff927e70Sdsl uint64_t rxfer;
25612749a2aSjtc
2579368f38eSmlelstv /* elapsed time for disk stats */
2589368f38eSmlelstv dtime = etime;
2599368f38eSmlelstv if (cur.timestamp[dn].tv_sec || cur.timestamp[dn].tv_usec)
2609368f38eSmlelstv dtime = (double)cur.timestamp[dn].tv_sec +
2619368f38eSmlelstv ((double)cur.timestamp[dn].tv_usec / (double)1000000);
2629368f38eSmlelstv
2631eaf5ee3Sthorpej /* time busy in disk activity */
264e48af18bSblymn atime = (double)cur.time[dn].tv_sec +
265e48af18bSblymn ((double)cur.time[dn].tv_usec / (double)1000000);
2661eaf5ee3Sthorpej
2673cf4c73dSmrg /* # of k transferred */
268e48af18bSblymn rwords = cur.rbytes[dn] / 1024.0;
269e48af18bSblymn wwords = cur.wbytes[dn] / 1024.0;
270e48af18bSblymn rxfer = cur.rxfer[dn];
271ff927e70Sdsl if (!read_write) {
272efc0bc90Sdsl rwords += wwords;
273e48af18bSblymn rxfer += cur.wxfer[dn];
274ff927e70Sdsl }
27512749a2aSjtc if (numbers) {
276f62ff76fSdsl mvwprintw(wnd, row, col, "%5.0f%4.0f",
2779368f38eSmlelstv rwords / dtime, rxfer / dtime);
278ff927e70Sdsl if (secs)
2799368f38eSmlelstv wprintw(wnd, "%5.1f", atime / dtime);
2803cf4c73dSmrg if (read_write)
281f62ff76fSdsl wprintw(wnd, " %5.0f%4.0f",
2829368f38eSmlelstv wwords / dtime, cur.wxfer[dn] / dtime);
28312749a2aSjtc return (row);
28412749a2aSjtc }
2853cf4c73dSmrg
28612749a2aSjtc wmove(wnd, row++, col);
2879368f38eSmlelstv histogram(rwords / dtime, 50, 0.5);
28812749a2aSjtc wmove(wnd, row++, col);
2899368f38eSmlelstv histogram(rxfer / dtime, 50, 0.5);
290ff927e70Sdsl if (read_write) {
2913cf4c73dSmrg wmove(wnd, row++, col);
2929368f38eSmlelstv histogram(wwords / dtime, 50, 0.5);
2933cf4c73dSmrg wmove(wnd, row++, col);
2949368f38eSmlelstv histogram(cur.wxfer[dn] / dtime, 50, 0.5);
295132bb1feSblymn }
296132bb1feSblymn
297132bb1feSblymn if (secs) {
298132bb1feSblymn wmove(wnd, row++, col);
299132bb1feSblymn atime *= 1000; /* In milliseconds */
3009368f38eSmlelstv histogram(atime / dtime, 50, 0.5);
301132bb1feSblymn }
302132bb1feSblymn return (row);
303132bb1feSblymn }
304132bb1feSblymn
30512749a2aSjtc static void
stat1(int row,int o)306fc391547Sad stat1(int row, int o)
30712749a2aSjtc {
308e7a39c4fSlukem size_t i;
309ff927e70Sdsl double total_time;
31012749a2aSjtc
311ff927e70Sdsl total_time = 0;
31212749a2aSjtc for (i = 0; i < CPUSTATES; i++)
313ff927e70Sdsl total_time += cur.cp_time[i];
314ff927e70Sdsl if (total_time == 0.0)
315ff927e70Sdsl total_time = 1.0;
31612749a2aSjtc wmove(wnd, row, INSET);
31712749a2aSjtc #define CPUSCALE 0.5
318ff927e70Sdsl histogram(100.0 * cur.cp_time[o] / total_time, 50, CPUSCALE);
31912749a2aSjtc }
32012749a2aSjtc
32112749a2aSjtc static void
histogram(double val,int colwidth,double scale)322fc391547Sad histogram(double val, int colwidth, double scale)
32312749a2aSjtc {
324b3467bbfSdsl int v = (int)(val * scale + 0.5);
325b3467bbfSdsl int factor = 1;
326b3467bbfSdsl int y, x;
32712749a2aSjtc
328b3467bbfSdsl while (v > colwidth) {
329b3467bbfSdsl v = (v + 5) / 10;
330b3467bbfSdsl factor *= 10;
33112749a2aSjtc }
332b3467bbfSdsl getyx(wnd, y, x);
33312749a2aSjtc wclrtoeol(wnd);
334b3467bbfSdsl whline(wnd, 'X', v);
335b3467bbfSdsl if (factor != 1)
336b3467bbfSdsl mvwprintw(wnd, y, x + colwidth + 1, "* %d ", factor);
33712749a2aSjtc }
33812749a2aSjtc
3394c0fbd4cSjwise void
iostat_bars(char * args)340fc391547Sad iostat_bars(char *args)
34112749a2aSjtc {
34212749a2aSjtc numbers = 0;
34312749a2aSjtc wclear(wnd);
34412749a2aSjtc labeliostat();
34512749a2aSjtc refresh();
3464c0fbd4cSjwise }
3474c0fbd4cSjwise
3484c0fbd4cSjwise void
iostat_numbers(char * args)349fc391547Sad iostat_numbers(char *args)
3504c0fbd4cSjwise {
3514c0fbd4cSjwise numbers = 1;
3524c0fbd4cSjwise wclear(wnd);
3534c0fbd4cSjwise labeliostat();
3544c0fbd4cSjwise refresh();
3554c0fbd4cSjwise }
3564c0fbd4cSjwise
3574c0fbd4cSjwise void
iostat_secs(char * args)358fc391547Sad iostat_secs(char *args)
3594c0fbd4cSjwise {
3604c0fbd4cSjwise secs = !secs;
3614c0fbd4cSjwise wclear(wnd);
3624c0fbd4cSjwise labeliostat();
3634c0fbd4cSjwise refresh();
36412749a2aSjtc }
3653cf4c73dSmrg
3663cf4c73dSmrg void
iostat_rw(char * args)3673cf4c73dSmrg iostat_rw(char *args)
3683cf4c73dSmrg {
369ff927e70Sdsl read_write ^= 1;
3703cf4c73dSmrg wclear(wnd);
3713cf4c73dSmrg labeliostat();
3723cf4c73dSmrg refresh();
3733cf4c73dSmrg }
3743cf4c73dSmrg
3753cf4c73dSmrg void
iostat_all(char * args)3763cf4c73dSmrg iostat_all(char *args)
3773cf4c73dSmrg {
3783cf4c73dSmrg read_write = 0;
3793cf4c73dSmrg wclear(wnd);
3803cf4c73dSmrg labeliostat();
3813cf4c73dSmrg refresh();
3823cf4c73dSmrg }
383