iostat.c revision 4930
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1992, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 351590Srgrimesstatic char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93"; 361590Srgrimes#endif not lint 371590Srgrimes 381590Srgrimes#include <sys/param.h> 391590Srgrimes#include <sys/dkstat.h> 401590Srgrimes#include <sys/buf.h> 411590Srgrimes 421590Srgrimes#include <string.h> 431590Srgrimes#include <stdlib.h> 441590Srgrimes#include <nlist.h> 451590Srgrimes#include <paths.h> 461590Srgrimes#include "systat.h" 471590Srgrimes#include "extern.h" 481590Srgrimes 491590Srgrimesstatic struct nlist namelist[] = { 501590Srgrimes#define X_DK_BUSY 0 511590Srgrimes { "_dk_busy" }, 521590Srgrimes#define X_DK_TIME 1 531590Srgrimes { "_dk_time" }, 541590Srgrimes#define X_DK_XFER 2 551590Srgrimes { "_dk_xfer" }, 561590Srgrimes#define X_DK_WDS 3 571590Srgrimes { "_dk_wds" }, 581590Srgrimes#define X_DK_SEEK 4 591590Srgrimes { "_dk_seek" }, 601590Srgrimes#define X_CP_TIME 5 611590Srgrimes { "_cp_time" }, 621590Srgrimes#ifdef vax 631590Srgrimes#define X_MBDINIT (X_CP_TIME+1) 641590Srgrimes { "_mbdinit" }, 651590Srgrimes#define X_UBDINIT (X_CP_TIME+2) 661590Srgrimes { "_ubdinit" }, 671590Srgrimes#endif 681590Srgrimes#ifdef tahoe 691590Srgrimes#define X_VBDINIT (X_CP_TIME+1) 701590Srgrimes { "_vbdinit" }, 711590Srgrimes#endif 721590Srgrimes { "" }, 731590Srgrimes}; 741590Srgrimes 751590Srgrimesstatic struct { 761590Srgrimes int dk_busy; 771590Srgrimes long cp_time[CPUSTATES]; 781590Srgrimes long *dk_time; 791590Srgrimes long *dk_wds; 801590Srgrimes long *dk_seek; 811590Srgrimes long *dk_xfer; 821590Srgrimes} s, s1; 831590Srgrimes 841590Srgrimesstatic int linesperregion; 851590Srgrimesstatic double etime; 861590Srgrimesstatic int numbers = 0; /* default display bar graphs */ 871590Srgrimesstatic int msps = 0; /* default ms/seek shown */ 881590Srgrimes 891590Srgrimesstatic int barlabels __P((int)); 901590Srgrimesstatic void histogram __P((double, int, double)); 911590Srgrimesstatic int numlabels __P((int)); 921590Srgrimesstatic int stats __P((int, int, int)); 931590Srgrimesstatic void stat1 __P((int, int)); 941590Srgrimes 951590Srgrimes 961590SrgrimesWINDOW * 971590Srgrimesopeniostat() 981590Srgrimes{ 991590Srgrimes return (subwin(stdscr, LINES-1-5, 0, 5, 0)); 1001590Srgrimes} 1011590Srgrimes 1021590Srgrimesvoid 1031590Srgrimescloseiostat(w) 1041590Srgrimes WINDOW *w; 1051590Srgrimes{ 1061590Srgrimes if (w == NULL) 1071590Srgrimes return; 1081590Srgrimes wclear(w); 1091590Srgrimes wrefresh(w); 1101590Srgrimes delwin(w); 1111590Srgrimes} 1121590Srgrimes 1131590Srgrimesint 1141590Srgrimesinitiostat() 1151590Srgrimes{ 1161590Srgrimes if (namelist[X_DK_BUSY].n_type == 0) { 1171590Srgrimes if (kvm_nlist(kd, namelist)) { 1181590Srgrimes nlisterr(namelist); 1191590Srgrimes return(0); 1201590Srgrimes } 1211590Srgrimes if (namelist[X_DK_BUSY].n_type == 0) { 1221590Srgrimes error("Disk init information isn't in namelist"); 1231590Srgrimes return(0); 1241590Srgrimes } 1251590Srgrimes } 1261590Srgrimes if (! dkinit()) 1271590Srgrimes return(0); 1281590Srgrimes if (dk_ndrive) { 1291590Srgrimes#define allocate(e, t) \ 1301590Srgrimes s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \ 1311590Srgrimes s1./**/e = (t *)calloc(dk_ndrive, sizeof (t)); 1321590Srgrimes allocate(dk_time, long); 1331590Srgrimes allocate(dk_wds, long); 1341590Srgrimes allocate(dk_seek, long); 1351590Srgrimes allocate(dk_xfer, long); 1361590Srgrimes#undef allocate 1371590Srgrimes } 1381590Srgrimes return(1); 1391590Srgrimes} 1401590Srgrimes 1411590Srgrimesvoid 1421590Srgrimesfetchiostat() 1431590Srgrimes{ 1441590Srgrimes if (namelist[X_DK_BUSY].n_type == 0) 1451590Srgrimes return; 1461590Srgrimes NREAD(X_DK_BUSY, &s.dk_busy, LONG); 1471590Srgrimes NREAD(X_DK_TIME, s.dk_time, dk_ndrive * LONG); 1481590Srgrimes NREAD(X_DK_XFER, s.dk_xfer, dk_ndrive * LONG); 1491590Srgrimes NREAD(X_DK_WDS, s.dk_wds, dk_ndrive * LONG); 1501590Srgrimes NREAD(X_DK_SEEK, s.dk_seek, dk_ndrive * LONG); 1511590Srgrimes NREAD(X_CP_TIME, s.cp_time, sizeof s.cp_time); 1521590Srgrimes} 1531590Srgrimes 1541590Srgrimes#define INSET 10 1551590Srgrimes 1561590Srgrimesvoid 1571590Srgrimeslabeliostat() 1581590Srgrimes{ 1591590Srgrimes int row; 1601590Srgrimes 1611590Srgrimes if (namelist[X_DK_BUSY].n_type == 0) { 1621590Srgrimes error("No dk_busy defined."); 1631590Srgrimes return; 1641590Srgrimes } 1651590Srgrimes row = 0; 1661590Srgrimes wmove(wnd, row, 0); wclrtobot(wnd); 1671590Srgrimes mvwaddstr(wnd, row++, INSET, 1681590Srgrimes "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); 1691590Srgrimes mvwaddstr(wnd, row++, 0, "cpu user|"); 1701590Srgrimes mvwaddstr(wnd, row++, 0, " nice|"); 1711590Srgrimes mvwaddstr(wnd, row++, 0, " system|"); 1724930Sbde mvwaddstr(wnd, row++, 0, "interrupt|"); 1731590Srgrimes mvwaddstr(wnd, row++, 0, " idle|"); 1741590Srgrimes if (numbers) 1751590Srgrimes row = numlabels(row + 1); 1761590Srgrimes else 1771590Srgrimes row = barlabels(row + 1); 1781590Srgrimes} 1791590Srgrimes 1801590Srgrimesstatic int 1811590Srgrimesnumlabels(row) 1821590Srgrimes int row; 1831590Srgrimes{ 1841590Srgrimes int i, col, regions, ndrives; 1851590Srgrimes 1861590Srgrimes#define COLWIDTH 14 1871590Srgrimes#define DRIVESPERLINE ((wnd->maxx - INSET) / COLWIDTH) 1881590Srgrimes for (ndrives = 0, i = 0; i < dk_ndrive; i++) 1891590Srgrimes if (dk_select[i]) 1901590Srgrimes ndrives++; 1911590Srgrimes regions = howmany(ndrives, DRIVESPERLINE); 1921590Srgrimes /* 1931590Srgrimes * Deduct -regions for blank line after each scrolling region. 1941590Srgrimes */ 1951590Srgrimes linesperregion = (wnd->maxy - row - regions) / regions; 1961590Srgrimes /* 1971590Srgrimes * Minimum region contains space for two 1981590Srgrimes * label lines and one line of statistics. 1991590Srgrimes */ 2001590Srgrimes if (linesperregion < 3) 2011590Srgrimes linesperregion = 3; 2021590Srgrimes col = 0; 2031590Srgrimes for (i = 0; i < dk_ndrive; i++) 2041590Srgrimes if (dk_select[i] && dk_mspw[i] != 0.0) { 2051590Srgrimes if (col + COLWIDTH >= wnd->maxx - INSET) { 2061590Srgrimes col = 0, row += linesperregion + 1; 2071590Srgrimes if (row > wnd->maxy - (linesperregion + 1)) 2081590Srgrimes break; 2091590Srgrimes } 2101590Srgrimes mvwaddstr(wnd, row, col + 4, dr_name[i]); 2111590Srgrimes mvwaddstr(wnd, row + 1, col, "bps tps msps"); 2121590Srgrimes col += COLWIDTH; 2131590Srgrimes } 2141590Srgrimes if (col) 2151590Srgrimes row += linesperregion + 1; 2161590Srgrimes return (row); 2171590Srgrimes} 2181590Srgrimes 2191590Srgrimesstatic int 2201590Srgrimesbarlabels(row) 2211590Srgrimes int row; 2221590Srgrimes{ 2231590Srgrimes int i; 2241590Srgrimes 2251590Srgrimes mvwaddstr(wnd, row++, INSET, 2261590Srgrimes "/0 /5 /10 /15 /20 /25 /30 /35 /40 /45 /50"); 2271590Srgrimes linesperregion = 2 + msps; 2281590Srgrimes for (i = 0; i < dk_ndrive; i++) 2291590Srgrimes if (dk_select[i] && dk_mspw[i] != 0.0) { 2301590Srgrimes if (row > wnd->maxy - linesperregion) 2311590Srgrimes break; 2321590Srgrimes mvwprintw(wnd, row++, 0, "%3.3s bps|", dr_name[i]); 2331590Srgrimes mvwaddstr(wnd, row++, 0, " tps|"); 2341590Srgrimes if (msps) 2351590Srgrimes mvwaddstr(wnd, row++, 0, " msps|"); 2361590Srgrimes } 2371590Srgrimes return (row); 2381590Srgrimes} 2391590Srgrimes 2401590Srgrimes 2411590Srgrimesvoid 2421590Srgrimesshowiostat() 2431590Srgrimes{ 2441590Srgrimes register long t; 2451590Srgrimes register int i, row, col; 2461590Srgrimes 2471590Srgrimes if (namelist[X_DK_BUSY].n_type == 0) 2481590Srgrimes return; 2491590Srgrimes for (i = 0; i < dk_ndrive; i++) { 2501590Srgrimes#define X(fld) t = s.fld[i]; s.fld[i] -= s1.fld[i]; s1.fld[i] = t 2511590Srgrimes X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time); 2521590Srgrimes } 2531590Srgrimes etime = 0; 2541590Srgrimes for(i = 0; i < CPUSTATES; i++) { 2551590Srgrimes X(cp_time); 2561590Srgrimes etime += s.cp_time[i]; 2571590Srgrimes } 2581590Srgrimes if (etime == 0.0) 2591590Srgrimes etime = 1.0; 2604930Sbde etime /= hertz; 2611590Srgrimes row = 1; 2624930Sbde for (i = 0; i < CPUSTATES; i++) 2631590Srgrimes stat1(row++, i); 2641590Srgrimes if (!numbers) { 2651590Srgrimes row += 2; 2661590Srgrimes for (i = 0; i < dk_ndrive; i++) 2671590Srgrimes if (dk_select[i] && dk_mspw[i] != 0.0) { 2681590Srgrimes if (row > wnd->maxy - linesperregion) 2691590Srgrimes break; 2701590Srgrimes row = stats(row, INSET, i); 2711590Srgrimes } 2721590Srgrimes return; 2731590Srgrimes } 2741590Srgrimes col = 0; 2751590Srgrimes wmove(wnd, row + linesperregion, 0); 2761590Srgrimes wdeleteln(wnd); 2771590Srgrimes wmove(wnd, row + 3, 0); 2781590Srgrimes winsertln(wnd); 2791590Srgrimes for (i = 0; i < dk_ndrive; i++) 2801590Srgrimes if (dk_select[i] && dk_mspw[i] != 0.0) { 2811590Srgrimes if (col + COLWIDTH >= wnd->maxx) { 2821590Srgrimes col = 0, row += linesperregion + 1; 2831590Srgrimes if (row > wnd->maxy - (linesperregion + 1)) 2841590Srgrimes break; 2851590Srgrimes wmove(wnd, row + linesperregion, 0); 2861590Srgrimes wdeleteln(wnd); 2871590Srgrimes wmove(wnd, row + 3, 0); 2881590Srgrimes winsertln(wnd); 2891590Srgrimes } 2901590Srgrimes (void) stats(row + 3, col, i); 2911590Srgrimes col += COLWIDTH; 2921590Srgrimes } 2931590Srgrimes} 2941590Srgrimes 2951590Srgrimesstatic int 2961590Srgrimesstats(row, col, dn) 2971590Srgrimes int row, col, dn; 2981590Srgrimes{ 2991590Srgrimes double atime, words, xtime, itime; 3001590Srgrimes 3011590Srgrimes atime = s.dk_time[dn]; 3024930Sbde atime /= hertz; 3031590Srgrimes words = s.dk_wds[dn]*32.0; /* number of words transferred */ 3041590Srgrimes xtime = dk_mspw[dn]*words; /* transfer time */ 3051590Srgrimes itime = atime - xtime; /* time not transferring */ 3061590Srgrimes if (xtime < 0) 3071590Srgrimes itime += xtime, xtime = 0; 3081590Srgrimes if (itime < 0) 3091590Srgrimes xtime += itime, itime = 0; 3101590Srgrimes if (numbers) { 3111590Srgrimes mvwprintw(wnd, row, col, "%3.0f%4.0f%5.1f", 3121590Srgrimes words / 512 / etime, s.dk_xfer[dn] / etime, 3131590Srgrimes s.dk_seek[dn] ? itime * 1000. / s.dk_seek[dn] : 0.0); 3141590Srgrimes return (row); 3151590Srgrimes } 3161590Srgrimes wmove(wnd, row++, col); 3171590Srgrimes histogram(words / 512 / etime, 50, 1.0); 3181590Srgrimes wmove(wnd, row++, col); 3191590Srgrimes histogram(s.dk_xfer[dn] / etime, 50, 1.0); 3201590Srgrimes if (msps) { 3211590Srgrimes wmove(wnd, row++, col); 3221590Srgrimes histogram(s.dk_seek[dn] ? itime * 1000. / s.dk_seek[dn] : 0, 3231590Srgrimes 50, 1.0); 3241590Srgrimes } 3251590Srgrimes return (row); 3261590Srgrimes} 3271590Srgrimes 3281590Srgrimesstatic void 3291590Srgrimesstat1(row, o) 3301590Srgrimes int row, o; 3311590Srgrimes{ 3321590Srgrimes register int i; 3331590Srgrimes double time; 3341590Srgrimes 3351590Srgrimes time = 0; 3361590Srgrimes for (i = 0; i < CPUSTATES; i++) 3371590Srgrimes time += s.cp_time[i]; 3381590Srgrimes if (time == 0.0) 3391590Srgrimes time = 1.0; 3401590Srgrimes wmove(wnd, row, INSET); 3411590Srgrimes#define CPUSCALE 0.5 3421590Srgrimes histogram(100.0 * s.cp_time[o] / time, 50, CPUSCALE); 3431590Srgrimes} 3441590Srgrimes 3451590Srgrimesstatic void 3461590Srgrimeshistogram(val, colwidth, scale) 3471590Srgrimes double val; 3481590Srgrimes int colwidth; 3491590Srgrimes double scale; 3501590Srgrimes{ 3511590Srgrimes char buf[10]; 3521590Srgrimes register int k; 3531590Srgrimes register int v = (int)(val * scale) + 0.5; 3541590Srgrimes 3551590Srgrimes k = MIN(v, colwidth); 3561590Srgrimes if (v > colwidth) { 3571590Srgrimes sprintf(buf, "%4.1f", val); 3581590Srgrimes k -= strlen(buf); 3591590Srgrimes while (k--) 3601590Srgrimes waddch(wnd, 'X'); 3611590Srgrimes waddstr(wnd, buf); 3621590Srgrimes return; 3631590Srgrimes } 3641590Srgrimes while (k--) 3651590Srgrimes waddch(wnd, 'X'); 3661590Srgrimes wclrtoeol(wnd); 3671590Srgrimes} 3681590Srgrimes 3691590Srgrimesint 3701590Srgrimescmdiostat(cmd, args) 3711590Srgrimes char *cmd, *args; 3721590Srgrimes{ 3731590Srgrimes 3741590Srgrimes if (prefix(cmd, "msps")) 3751590Srgrimes msps = !msps; 3761590Srgrimes else if (prefix(cmd, "numbers")) 3771590Srgrimes numbers = 1; 3781590Srgrimes else if (prefix(cmd, "bars")) 3791590Srgrimes numbers = 0; 3801590Srgrimes else if (!dkcmd(cmd, args)) 3811590Srgrimes return (0); 3821590Srgrimes wclear(wnd); 3831590Srgrimes labeliostat(); 3841590Srgrimes refresh(); 3851590Srgrimes return (1); 3861590Srgrimes} 387