18d2fbde5SJustin T. Gibbs /* 25dc445bfSKenneth D. Merry * Copyright (c) 1997, 1998, 2000, 2001 Kenneth D. Merry 38d2fbde5SJustin T. Gibbs * All rights reserved. 48d2fbde5SJustin T. Gibbs * 58d2fbde5SJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 68d2fbde5SJustin T. Gibbs * modification, are permitted provided that the following conditions 78d2fbde5SJustin T. Gibbs * are met: 88d2fbde5SJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 98d2fbde5SJustin T. Gibbs * notice, this list of conditions and the following disclaimer. 108d2fbde5SJustin T. Gibbs * 2. Redistributions in binary form must reproduce the above copyright 118d2fbde5SJustin T. Gibbs * notice, this list of conditions and the following disclaimer in the 128d2fbde5SJustin T. Gibbs * documentation and/or other materials provided with the distribution. 138d2fbde5SJustin T. Gibbs * 3. The name of the author may not be used to endorse or promote products 148d2fbde5SJustin T. Gibbs * derived from this software without specific prior written permission. 158d2fbde5SJustin T. Gibbs * 168d2fbde5SJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 178d2fbde5SJustin T. Gibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 188d2fbde5SJustin T. Gibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 198d2fbde5SJustin T. Gibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 208d2fbde5SJustin T. Gibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 218d2fbde5SJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 228d2fbde5SJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 238d2fbde5SJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 248d2fbde5SJustin T. Gibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 258d2fbde5SJustin T. Gibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 268d2fbde5SJustin T. Gibbs * SUCH DAMAGE. 278743d3dcSPhilippe Charnier * 288743d3dcSPhilippe Charnier * $FreeBSD$ 298d2fbde5SJustin T. Gibbs */ 308d2fbde5SJustin T. Gibbs /* 318d2fbde5SJustin T. Gibbs * Parts of this program are derived from the original FreeBSD iostat 328d2fbde5SJustin T. Gibbs * program: 338d2fbde5SJustin T. Gibbs */ 34dea673e9SRodney W. Grimes /*- 35dea673e9SRodney W. Grimes * Copyright (c) 1986, 1991, 1993 36dea673e9SRodney W. Grimes * The Regents of the University of California. All rights reserved. 37dea673e9SRodney W. Grimes * 38dea673e9SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 39dea673e9SRodney W. Grimes * modification, are permitted provided that the following conditions 40dea673e9SRodney W. Grimes * are met: 41dea673e9SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 42dea673e9SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 43dea673e9SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 44dea673e9SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 45dea673e9SRodney W. Grimes * documentation and/or other materials provided with the distribution. 46dea673e9SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 47dea673e9SRodney W. Grimes * must display the following acknowledgement: 48dea673e9SRodney W. Grimes * This product includes software developed by the University of 49dea673e9SRodney W. Grimes * California, Berkeley and its contributors. 50dea673e9SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 51dea673e9SRodney W. Grimes * may be used to endorse or promote products derived from this software 52dea673e9SRodney W. Grimes * without specific prior written permission. 53dea673e9SRodney W. Grimes * 54dea673e9SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55dea673e9SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56dea673e9SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57dea673e9SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58dea673e9SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59dea673e9SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60dea673e9SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61dea673e9SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62dea673e9SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63dea673e9SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64dea673e9SRodney W. Grimes * SUCH DAMAGE. 65dea673e9SRodney W. Grimes */ 668d2fbde5SJustin T. Gibbs /* 678d2fbde5SJustin T. Gibbs * Ideas for the new iostat statistics output modes taken from the NetBSD 688d2fbde5SJustin T. Gibbs * version of iostat: 698d2fbde5SJustin T. Gibbs */ 708d2fbde5SJustin T. Gibbs /* 718d2fbde5SJustin T. Gibbs * Copyright (c) 1996 John M. Vinopal 728d2fbde5SJustin T. Gibbs * All rights reserved. 738d2fbde5SJustin T. Gibbs * 748d2fbde5SJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 758d2fbde5SJustin T. Gibbs * modification, are permitted provided that the following conditions 768d2fbde5SJustin T. Gibbs * are met: 778d2fbde5SJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 788d2fbde5SJustin T. Gibbs * notice, this list of conditions and the following disclaimer. 798d2fbde5SJustin T. Gibbs * 2. Redistributions in binary form must reproduce the above copyright 808d2fbde5SJustin T. Gibbs * notice, this list of conditions and the following disclaimer in the 818d2fbde5SJustin T. Gibbs * documentation and/or other materials provided with the distribution. 828d2fbde5SJustin T. Gibbs * 3. All advertising materials mentioning features or use of this software 838d2fbde5SJustin T. Gibbs * must display the following acknowledgement: 848d2fbde5SJustin T. Gibbs * This product includes software developed for the NetBSD Project 858d2fbde5SJustin T. Gibbs * by John M. Vinopal. 868d2fbde5SJustin T. Gibbs * 4. The name of the author may not be used to endorse or promote products 878d2fbde5SJustin T. Gibbs * derived from this software without specific prior written permission. 888d2fbde5SJustin T. Gibbs * 898d2fbde5SJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 908d2fbde5SJustin T. Gibbs * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 918d2fbde5SJustin T. Gibbs * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 928d2fbde5SJustin T. Gibbs * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 938d2fbde5SJustin T. Gibbs * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 948d2fbde5SJustin T. Gibbs * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 958d2fbde5SJustin T. Gibbs * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 968d2fbde5SJustin T. Gibbs * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 978d2fbde5SJustin T. Gibbs * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 988d2fbde5SJustin T. Gibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 998d2fbde5SJustin T. Gibbs * SUCH DAMAGE. 1008d2fbde5SJustin T. Gibbs */ 101dea673e9SRodney W. Grimes 102dea673e9SRodney W. Grimes 103dea673e9SRodney W. Grimes #include <sys/param.h> 1048d2fbde5SJustin T. Gibbs #include <sys/errno.h> 105190ff54eSPoul-Henning Kamp #include <sys/resource.h> 1065fc5ae5cSThomas Moestl #include <sys/sysctl.h> 107dea673e9SRodney W. Grimes 108dea673e9SRodney W. Grimes #include <err.h> 109dea673e9SRodney W. Grimes #include <ctype.h> 110dea673e9SRodney W. Grimes #include <fcntl.h> 111dea673e9SRodney W. Grimes #include <kvm.h> 1122757068eSBruce Evans #include <nlist.h> 113dea673e9SRodney W. Grimes #include <stdio.h> 114dea673e9SRodney W. Grimes #include <stdlib.h> 115dea673e9SRodney W. Grimes #include <string.h> 11653fbcd3aSGiorgos Keramidas #include <termios.h> 117dea673e9SRodney W. Grimes #include <unistd.h> 1188d2fbde5SJustin T. Gibbs #include <limits.h> 1198d2fbde5SJustin T. Gibbs #include <devstat.h> 1205dc445bfSKenneth D. Merry #include <math.h> 121dea673e9SRodney W. Grimes 122dea673e9SRodney W. Grimes struct nlist namelist[] = { 1238d2fbde5SJustin T. Gibbs #define X_TK_NIN 0 124dea673e9SRodney W. Grimes { "_tk_nin" }, 1258d2fbde5SJustin T. Gibbs #define X_TK_NOUT 1 126dea673e9SRodney W. Grimes { "_tk_nout" }, 12732c9e3bdSJohn Baldwin #define X_BOOTTIME 2 1285dc445bfSKenneth D. Merry { "_boottime" }, 12932c9e3bdSJohn Baldwin #define X_END 2 130dea673e9SRodney W. Grimes { NULL }, 131dea673e9SRodney W. Grimes }; 132dea673e9SRodney W. Grimes 13353fbcd3aSGiorgos Keramidas #define IOSTAT_DEFAULT_ROWS 20 /* Traditional default `wrows' */ 13453fbcd3aSGiorgos Keramidas 1358d2fbde5SJustin T. Gibbs struct statinfo cur, last; 1368d2fbde5SJustin T. Gibbs int num_devices; 1378d2fbde5SJustin T. Gibbs struct device_selection *dev_select; 1388d2fbde5SJustin T. Gibbs int maxshowdevs; 139775b0074SGuido van Rooij volatile sig_atomic_t headercount; 14053fbcd3aSGiorgos Keramidas volatile sig_atomic_t wresized; /* Tty resized, when non-zero. */ 14153fbcd3aSGiorgos Keramidas unsigned short wrows; /* Current number of tty rows. */ 1422fa4aaa0SMatthew Dillon int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0; 1436c359123SMaxim Konovalov int xflag = 0, zflag = 0; 144dea673e9SRodney W. Grimes 1458d2fbde5SJustin T. Gibbs /* local function declarations */ 1468d2fbde5SJustin T. Gibbs static void usage(void); 147775b0074SGuido van Rooij static void needhdr(int signo); 14853fbcd3aSGiorgos Keramidas static void needresize(int signo); 14953fbcd3aSGiorgos Keramidas static void doresize(void); 150775b0074SGuido van Rooij static void phdr(void); 1515dc445bfSKenneth D. Merry static void devstats(int perf_select, long double etime, int havelast); 1528d2fbde5SJustin T. Gibbs static void cpustats(void); 1535dc445bfSKenneth D. Merry static int readvar(kvm_t *kd, const char *name, int nlid, void *ptr, 1545dc445bfSKenneth D. Merry size_t len); 155dea673e9SRodney W. Grimes 1568d2fbde5SJustin T. Gibbs static void 1578d2fbde5SJustin T. Gibbs usage(void) 1588d2fbde5SJustin T. Gibbs { 1598d2fbde5SJustin T. Gibbs /* 1608d2fbde5SJustin T. Gibbs * We also support the following 'traditional' syntax: 1618d2fbde5SJustin T. Gibbs * iostat [drives] [wait [count]] 1628d2fbde5SJustin T. Gibbs * This isn't mentioned in the man page, or the usage statement, 1638d2fbde5SJustin T. Gibbs * but it is supported. 1648d2fbde5SJustin T. Gibbs */ 1656c359123SMaxim Konovalov fprintf(stderr, "usage: iostat [-CdhIKoTxz?] [-c count] [-M core]" 1668743d3dcSPhilippe Charnier " [-n devs] [-N system]\n" 1678743d3dcSPhilippe Charnier "\t [-t type,if,pass] [-w wait] [drives]\n"); 1688d2fbde5SJustin T. Gibbs } 169dea673e9SRodney W. Grimes 170dea673e9SRodney W. Grimes int 1718d2fbde5SJustin T. Gibbs main(int argc, char **argv) 172dea673e9SRodney W. Grimes { 17347e065b4SMaxim Konovalov int c, i; 1748d2fbde5SJustin T. Gibbs int tflag = 0, hflag = 0, cflag = 0, wflag = 0, nflag = 0; 1758d2fbde5SJustin T. Gibbs int count = 0, waittime = 0; 1768d2fbde5SJustin T. Gibbs char *memf = NULL, *nlistf = NULL; 1778d2fbde5SJustin T. Gibbs struct devstat_match *matches; 1788d2fbde5SJustin T. Gibbs int num_matches = 0; 179dea673e9SRodney W. Grimes char errbuf[_POSIX2_LINE_MAX]; 1805fc5ae5cSThomas Moestl kvm_t *kd = NULL; 181bcc6a3daSKenneth D. Merry long generation; 1828d2fbde5SJustin T. Gibbs int num_devices_specified; 183bcc6a3daSKenneth D. Merry int num_selected, num_selections; 184bcc6a3daSKenneth D. Merry long select_generation; 1858d2fbde5SJustin T. Gibbs char **specified_devices; 1868d2fbde5SJustin T. Gibbs devstat_select_mode select_mode; 187*8b10473dSSean Bruno float f; 1885dc445bfSKenneth D. Merry int havelast = 0; 189dea673e9SRodney W. Grimes 1908d2fbde5SJustin T. Gibbs matches = NULL; 1918d2fbde5SJustin T. Gibbs maxshowdevs = 3; 1928d2fbde5SJustin T. Gibbs 1936c359123SMaxim Konovalov while ((c = getopt(argc, argv, "c:CdhIKM:n:N:ot:Tw:xz?")) != -1) { 1948d2fbde5SJustin T. Gibbs switch(c) { 195dea673e9SRodney W. Grimes case 'c': 1968d2fbde5SJustin T. Gibbs cflag++; 1978d2fbde5SJustin T. Gibbs count = atoi(optarg); 1988d2fbde5SJustin T. Gibbs if (count < 1) 1998d2fbde5SJustin T. Gibbs errx(1, "count %d is < 1", count); 2008d2fbde5SJustin T. Gibbs break; 2018d2fbde5SJustin T. Gibbs case 'C': 2028d2fbde5SJustin T. Gibbs Cflag++; 2038d2fbde5SJustin T. Gibbs break; 2048d2fbde5SJustin T. Gibbs case 'd': 2058d2fbde5SJustin T. Gibbs dflag++; 2068d2fbde5SJustin T. Gibbs break; 2078d2fbde5SJustin T. Gibbs case 'h': 2088d2fbde5SJustin T. Gibbs hflag++; 2098d2fbde5SJustin T. Gibbs break; 2108d2fbde5SJustin T. Gibbs case 'I': 2118d2fbde5SJustin T. Gibbs Iflag++; 212dea673e9SRodney W. Grimes break; 213e4d7fe02SKenneth D. Merry case 'K': 214e4d7fe02SKenneth D. Merry Kflag++; 215e4d7fe02SKenneth D. Merry break; 216dea673e9SRodney W. Grimes case 'M': 217dea673e9SRodney W. Grimes memf = optarg; 218dea673e9SRodney W. Grimes break; 2198d2fbde5SJustin T. Gibbs case 'n': 2208d2fbde5SJustin T. Gibbs nflag++; 2218d2fbde5SJustin T. Gibbs maxshowdevs = atoi(optarg); 2228d2fbde5SJustin T. Gibbs if (maxshowdevs < 0) 2235d4a8fa9SPhilippe Charnier errx(1, "number of devices %d is < 0", 2248d2fbde5SJustin T. Gibbs maxshowdevs); 2258d2fbde5SJustin T. Gibbs break; 226dea673e9SRodney W. Grimes case 'N': 227dea673e9SRodney W. Grimes nlistf = optarg; 228dea673e9SRodney W. Grimes break; 2298d2fbde5SJustin T. Gibbs case 'o': 2308d2fbde5SJustin T. Gibbs oflag++; 231dea673e9SRodney W. Grimes break; 2328d2fbde5SJustin T. Gibbs case 't': 2338d2fbde5SJustin T. Gibbs tflag++; 2345fc5ae5cSThomas Moestl if (devstat_buildmatch(optarg, &matches, 2358d2fbde5SJustin T. Gibbs &num_matches) != 0) 2368d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 2378d2fbde5SJustin T. Gibbs break; 2388d2fbde5SJustin T. Gibbs case 'T': 2398d2fbde5SJustin T. Gibbs Tflag++; 2408d2fbde5SJustin T. Gibbs break; 2418d2fbde5SJustin T. Gibbs case 'w': 2428d2fbde5SJustin T. Gibbs wflag++; 243*8b10473dSSean Bruno f = atof(optarg); 244*8b10473dSSean Bruno waittime = f * 1000; 2458d2fbde5SJustin T. Gibbs if (waittime < 1) 246*8b10473dSSean Bruno errx(1, "wait time is < 1ms"); 2478d2fbde5SJustin T. Gibbs break; 2486c359123SMaxim Konovalov case 'x': 2496c359123SMaxim Konovalov xflag++; 2506c359123SMaxim Konovalov break; 2516c359123SMaxim Konovalov case 'z': 2526c359123SMaxim Konovalov zflag++; 2536c359123SMaxim Konovalov break; 254dea673e9SRodney W. Grimes default: 255dea673e9SRodney W. Grimes usage(); 2568743d3dcSPhilippe Charnier exit(1); 2578d2fbde5SJustin T. Gibbs break; 258dea673e9SRodney W. Grimes } 2598d2fbde5SJustin T. Gibbs } 2608d2fbde5SJustin T. Gibbs 261dea673e9SRodney W. Grimes argc -= optind; 262dea673e9SRodney W. Grimes argv += optind; 263dea673e9SRodney W. Grimes 2645dc445bfSKenneth D. Merry if (nlistf != NULL || memf != NULL) { 2655fc5ae5cSThomas Moestl kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 2665fc5ae5cSThomas Moestl 2675dc445bfSKenneth D. Merry if (kd == NULL) 2685fc5ae5cSThomas Moestl errx(1, "kvm_openfiles: %s", errbuf); 2695fc5ae5cSThomas Moestl 2705fc5ae5cSThomas Moestl if (kvm_nlist(kd, namelist) == -1) 2715fc5ae5cSThomas Moestl errx(1, "kvm_nlist: %s", kvm_geterr(kd)); 2725fc5ae5cSThomas Moestl } 273dea673e9SRodney W. Grimes 2748d2fbde5SJustin T. Gibbs /* 2758d2fbde5SJustin T. Gibbs * Make sure that the userland devstat version matches the kernel 2768d2fbde5SJustin T. Gibbs * devstat version. If not, exit and print a message informing 2778d2fbde5SJustin T. Gibbs * the user of his mistake. 2788d2fbde5SJustin T. Gibbs */ 2795fc5ae5cSThomas Moestl if (devstat_checkversion(kd) < 0) 2808d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 2818d2fbde5SJustin T. Gibbs 2828d2fbde5SJustin T. Gibbs /* 2835dc445bfSKenneth D. Merry * Make sure Tflag and/or Cflag are set if dflag == 0. If dflag is 2845dc445bfSKenneth D. Merry * greater than 0, they may be 0 or non-zero. 2855dc445bfSKenneth D. Merry */ 2866c359123SMaxim Konovalov if (dflag == 0 && xflag == 0) { 2875dc445bfSKenneth D. Merry Cflag = 1; 2885dc445bfSKenneth D. Merry Tflag = 1; 2895dc445bfSKenneth D. Merry } 2905dc445bfSKenneth D. Merry 291dd9bccc4SMaxim Konovalov /* find out how many devices we have */ 292dd9bccc4SMaxim Konovalov if ((num_devices = devstat_getnumdevs(kd)) < 0) 293dd9bccc4SMaxim Konovalov err(1, "can't get number of devices"); 294dd9bccc4SMaxim Konovalov 2955dc445bfSKenneth D. Merry /* 2968d2fbde5SJustin T. Gibbs * Figure out how many devices we should display. 2978d2fbde5SJustin T. Gibbs */ 2988d2fbde5SJustin T. Gibbs if (nflag == 0) { 299dd9bccc4SMaxim Konovalov if (xflag > 0) 300dd9bccc4SMaxim Konovalov maxshowdevs = num_devices; 301dd9bccc4SMaxim Konovalov else if (oflag > 0) { 3028d2fbde5SJustin T. Gibbs if ((dflag > 0) && (Cflag == 0) && (Tflag == 0)) 3038d2fbde5SJustin T. Gibbs maxshowdevs = 5; 3048d2fbde5SJustin T. Gibbs else if ((dflag > 0) && (Tflag > 0) && (Cflag == 0)) 3058d2fbde5SJustin T. Gibbs maxshowdevs = 5; 3068d2fbde5SJustin T. Gibbs else 3078d2fbde5SJustin T. Gibbs maxshowdevs = 4; 3088d2fbde5SJustin T. Gibbs } else { 3098d2fbde5SJustin T. Gibbs if ((dflag > 0) && (Cflag == 0)) 3108d2fbde5SJustin T. Gibbs maxshowdevs = 4; 3118d2fbde5SJustin T. Gibbs else 3128d2fbde5SJustin T. Gibbs maxshowdevs = 3; 3138d2fbde5SJustin T. Gibbs } 3148d2fbde5SJustin T. Gibbs } 3158d2fbde5SJustin T. Gibbs 3164f6e1368SXin LI cur.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)); 3175dc445bfSKenneth D. Merry if (cur.dinfo == NULL) 3184f6e1368SXin LI err(1, "calloc failed"); 3195dc445bfSKenneth D. Merry 3204f6e1368SXin LI last.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)); 3215dc445bfSKenneth D. Merry if (last.dinfo == NULL) 3224f6e1368SXin LI err(1, "calloc failed"); 3238d2fbde5SJustin T. Gibbs 3248d2fbde5SJustin T. Gibbs /* 3258d2fbde5SJustin T. Gibbs * Grab all the devices. We don't look to see if the list has 3268d2fbde5SJustin T. Gibbs * changed here, since it almost certainly has. We only look for 3278d2fbde5SJustin T. Gibbs * errors. 3288d2fbde5SJustin T. Gibbs */ 3295fc5ae5cSThomas Moestl if (devstat_getdevs(kd, &cur) == -1) 3308d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 3318d2fbde5SJustin T. Gibbs 3328d2fbde5SJustin T. Gibbs num_devices = cur.dinfo->numdevs; 3338d2fbde5SJustin T. Gibbs generation = cur.dinfo->generation; 3348d2fbde5SJustin T. Gibbs 3358d2fbde5SJustin T. Gibbs /* 3368d2fbde5SJustin T. Gibbs * If the user specified any devices on the command line, see if 3378d2fbde5SJustin T. Gibbs * they are in the list of devices we have now. 3388d2fbde5SJustin T. Gibbs */ 3395dc445bfSKenneth D. Merry specified_devices = (char **)malloc(sizeof(char *)); 3405dc445bfSKenneth D. Merry if (specified_devices == NULL) 3415dc445bfSKenneth D. Merry err(1, "malloc failed"); 3425dc445bfSKenneth D. Merry 3438d2fbde5SJustin T. Gibbs for (num_devices_specified = 0; *argv; ++argv) { 3448d2fbde5SJustin T. Gibbs if (isdigit(**argv)) 3458d2fbde5SJustin T. Gibbs break; 3468d2fbde5SJustin T. Gibbs num_devices_specified++; 3478d2fbde5SJustin T. Gibbs specified_devices = (char **)realloc(specified_devices, 3488d2fbde5SJustin T. Gibbs sizeof(char *) * 3498d2fbde5SJustin T. Gibbs num_devices_specified); 3505dc445bfSKenneth D. Merry if (specified_devices == NULL) 3515dc445bfSKenneth D. Merry err(1, "realloc failed"); 3525dc445bfSKenneth D. Merry 3538d2fbde5SJustin T. Gibbs specified_devices[num_devices_specified - 1] = *argv; 3548d2fbde5SJustin T. Gibbs 3558d2fbde5SJustin T. Gibbs } 3562fa4aaa0SMatthew Dillon if (nflag == 0 && maxshowdevs < num_devices_specified) 3572fa4aaa0SMatthew Dillon maxshowdevs = num_devices_specified; 3588d2fbde5SJustin T. Gibbs 3598d2fbde5SJustin T. Gibbs dev_select = NULL; 3608d2fbde5SJustin T. Gibbs 3618d2fbde5SJustin T. Gibbs if ((num_devices_specified == 0) && (num_matches == 0)) 3628d2fbde5SJustin T. Gibbs select_mode = DS_SELECT_ADD; 3638d2fbde5SJustin T. Gibbs else 3648d2fbde5SJustin T. Gibbs select_mode = DS_SELECT_ONLY; 3658d2fbde5SJustin T. Gibbs 3668d2fbde5SJustin T. Gibbs /* 3678d2fbde5SJustin T. Gibbs * At this point, selectdevs will almost surely indicate that the 3688d2fbde5SJustin T. Gibbs * device list has changed, so we don't look for return values of 0 3698d2fbde5SJustin T. Gibbs * or 1. If we get back -1, though, there is an error. 3708d2fbde5SJustin T. Gibbs */ 3715fc5ae5cSThomas Moestl if (devstat_selectdevs(&dev_select, &num_selected, 3725fc5ae5cSThomas Moestl &num_selections, &select_generation, generation, 3735fc5ae5cSThomas Moestl cur.dinfo->devices, num_devices, matches, 3745fc5ae5cSThomas Moestl num_matches, specified_devices, 3755fc5ae5cSThomas Moestl num_devices_specified, select_mode, maxshowdevs, 3765fc5ae5cSThomas Moestl hflag) == -1) 3778d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 3788d2fbde5SJustin T. Gibbs 3798d2fbde5SJustin T. Gibbs /* 3808d2fbde5SJustin T. Gibbs * Look for the traditional wait time and count arguments. 3818d2fbde5SJustin T. Gibbs */ 3828d2fbde5SJustin T. Gibbs if (*argv) { 383*8b10473dSSean Bruno f = atof(*argv); 384*8b10473dSSean Bruno waittime = f * 1000; 3858d2fbde5SJustin T. Gibbs 3868d2fbde5SJustin T. Gibbs /* Let the user know he goofed, but keep going anyway */ 3878d2fbde5SJustin T. Gibbs if (wflag != 0) 3888d2fbde5SJustin T. Gibbs warnx("discarding previous wait interval, using" 389*8b10473dSSean Bruno " %g instead", waittime / 1000.0); 3908d2fbde5SJustin T. Gibbs wflag++; 3918d2fbde5SJustin T. Gibbs 3928d2fbde5SJustin T. Gibbs if (*++argv) { 3938d2fbde5SJustin T. Gibbs count = atoi(*argv); 3948d2fbde5SJustin T. Gibbs if (cflag != 0) 3958d2fbde5SJustin T. Gibbs warnx("discarding previous count, using %d" 3968d2fbde5SJustin T. Gibbs " instead", count); 3978d2fbde5SJustin T. Gibbs cflag++; 3988d2fbde5SJustin T. Gibbs } else 3998d2fbde5SJustin T. Gibbs count = -1; 4008d2fbde5SJustin T. Gibbs } 4018d2fbde5SJustin T. Gibbs 4028d2fbde5SJustin T. Gibbs /* 4038d2fbde5SJustin T. Gibbs * If the user specified a count, but not an interval, we default 4048d2fbde5SJustin T. Gibbs * to an interval of 1 second. 4058d2fbde5SJustin T. Gibbs */ 4068d2fbde5SJustin T. Gibbs if ((wflag == 0) && (cflag > 0)) 407*8b10473dSSean Bruno waittime = 1 * 1000; 4088d2fbde5SJustin T. Gibbs 4098d2fbde5SJustin T. Gibbs /* 4108d2fbde5SJustin T. Gibbs * If the user specified a wait time, but not a count, we want to 4118d2fbde5SJustin T. Gibbs * go on ad infinitum. This can be redundant if the user uses the 4128d2fbde5SJustin T. Gibbs * traditional method of specifying the wait, since in that case we 4138d2fbde5SJustin T. Gibbs * already set count = -1 above. Oh well. 4148d2fbde5SJustin T. Gibbs */ 4158d2fbde5SJustin T. Gibbs if ((wflag > 0) && (cflag == 0)) 4168d2fbde5SJustin T. Gibbs count = -1; 4178d2fbde5SJustin T. Gibbs 4189e5fbab2SJohn Baldwin bzero(cur.cp_time, sizeof(cur.cp_time)); 4195dc445bfSKenneth D. Merry cur.tk_nout = 0; 4205dc445bfSKenneth D. Merry cur.tk_nin = 0; 4215dc445bfSKenneth D. Merry 4225dc445bfSKenneth D. Merry /* 4237194d335SPoul-Henning Kamp * Set the snap time to the system boot time (ie: zero), so the 4247194d335SPoul-Henning Kamp * stats are calculated since system boot. 4255dc445bfSKenneth D. Merry */ 4267194d335SPoul-Henning Kamp cur.snap_time = 0; 4275dc445bfSKenneth D. Merry 428dea673e9SRodney W. Grimes /* 4298d2fbde5SJustin T. Gibbs * If the user stops the program (control-Z) and then resumes it, 4308d2fbde5SJustin T. Gibbs * print out the header again. 431dea673e9SRodney W. Grimes */ 432775b0074SGuido van Rooij (void)signal(SIGCONT, needhdr); 433dea673e9SRodney W. Grimes 43453fbcd3aSGiorgos Keramidas /* 43553fbcd3aSGiorgos Keramidas * If our standard output is a tty, then install a SIGWINCH handler 43653fbcd3aSGiorgos Keramidas * and set wresized so that our first iteration through the main 43753fbcd3aSGiorgos Keramidas * iostat loop will peek at the terminal's current rows to find out 43853fbcd3aSGiorgos Keramidas * how many lines can fit in a screenful of output. 43953fbcd3aSGiorgos Keramidas */ 44053fbcd3aSGiorgos Keramidas if (isatty(fileno(stdout)) != 0) { 44153fbcd3aSGiorgos Keramidas wresized = 1; 44253fbcd3aSGiorgos Keramidas (void)signal(SIGWINCH, needresize); 44353fbcd3aSGiorgos Keramidas } else { 44453fbcd3aSGiorgos Keramidas wresized = 0; 44553fbcd3aSGiorgos Keramidas wrows = IOSTAT_DEFAULT_ROWS; 44653fbcd3aSGiorgos Keramidas } 44753fbcd3aSGiorgos Keramidas 4488d2fbde5SJustin T. Gibbs for (headercount = 1;;) { 4498d2fbde5SJustin T. Gibbs struct devinfo *tmp_dinfo; 4508d2fbde5SJustin T. Gibbs long tmp; 4515dc445bfSKenneth D. Merry long double etime; 4525dc445bfSKenneth D. Merry 4535dc445bfSKenneth D. Merry if (Tflag > 0) { 4545dc445bfSKenneth D. Merry if ((readvar(kd, "kern.tty_nin", X_TK_NIN, &cur.tk_nin, 4555dc445bfSKenneth D. Merry sizeof(cur.tk_nin)) != 0) 4565dc445bfSKenneth D. Merry || (readvar(kd, "kern.tty_nout", X_TK_NOUT, 4575dc445bfSKenneth D. Merry &cur.tk_nout, sizeof(cur.tk_nout))!= 0)) { 4585dc445bfSKenneth D. Merry Tflag = 0; 4595dc445bfSKenneth D. Merry warnx("disabling TTY statistics"); 4605dc445bfSKenneth D. Merry } 4615dc445bfSKenneth D. Merry } 4625dc445bfSKenneth D. Merry 4635dc445bfSKenneth D. Merry if (Cflag > 0) { 46432c9e3bdSJohn Baldwin if (kd == NULL) { 46532c9e3bdSJohn Baldwin if (readvar(kd, "kern.cp_time", 0, 46632c9e3bdSJohn Baldwin &cur.cp_time, sizeof(cur.cp_time)) != 0) 4675dc445bfSKenneth D. Merry Cflag = 0; 46832c9e3bdSJohn Baldwin } else { 46932c9e3bdSJohn Baldwin if (kvm_getcptime(kd, cur.cp_time) < 0) { 47032c9e3bdSJohn Baldwin warnx("kvm_getcptime: %s", 47132c9e3bdSJohn Baldwin kvm_geterr(kd)); 47232c9e3bdSJohn Baldwin Cflag = 0; 4735dc445bfSKenneth D. Merry } 4745dc445bfSKenneth D. Merry } 47532c9e3bdSJohn Baldwin if (Cflag == 0) 47632c9e3bdSJohn Baldwin warnx("disabling CPU time statistics"); 47732c9e3bdSJohn Baldwin } 4788d2fbde5SJustin T. Gibbs 4798d2fbde5SJustin T. Gibbs if (!--headercount) { 480775b0074SGuido van Rooij phdr(); 48153fbcd3aSGiorgos Keramidas if (wresized != 0) 48253fbcd3aSGiorgos Keramidas doresize(); 48353fbcd3aSGiorgos Keramidas headercount = wrows; 484dea673e9SRodney W. Grimes } 4858d2fbde5SJustin T. Gibbs 4868d2fbde5SJustin T. Gibbs tmp_dinfo = last.dinfo; 4878d2fbde5SJustin T. Gibbs last.dinfo = cur.dinfo; 4888d2fbde5SJustin T. Gibbs cur.dinfo = tmp_dinfo; 4898d2fbde5SJustin T. Gibbs 4907194d335SPoul-Henning Kamp last.snap_time = cur.snap_time; 4918d2fbde5SJustin T. Gibbs 4928d2fbde5SJustin T. Gibbs /* 4938d2fbde5SJustin T. Gibbs * Here what we want to do is refresh our device stats. 4945fc5ae5cSThomas Moestl * devstat_getdevs() returns 1 when the device list has changed. 4958d2fbde5SJustin T. Gibbs * If the device list has changed, we want to go through 4968d2fbde5SJustin T. Gibbs * the selection process again, in case a device that we 4978d2fbde5SJustin T. Gibbs * were previously displaying has gone away. 4988d2fbde5SJustin T. Gibbs */ 4995fc5ae5cSThomas Moestl switch (devstat_getdevs(kd, &cur)) { 5008d2fbde5SJustin T. Gibbs case -1: 5018d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 5028d2fbde5SJustin T. Gibbs break; 5038d2fbde5SJustin T. Gibbs case 1: { 5048d2fbde5SJustin T. Gibbs int retval; 5058d2fbde5SJustin T. Gibbs 5068d2fbde5SJustin T. Gibbs num_devices = cur.dinfo->numdevs; 5078d2fbde5SJustin T. Gibbs generation = cur.dinfo->generation; 5085fc5ae5cSThomas Moestl retval = devstat_selectdevs(&dev_select, &num_selected, 5095fc5ae5cSThomas Moestl &num_selections, 5105fc5ae5cSThomas Moestl &select_generation, 5115fc5ae5cSThomas Moestl generation, 5125fc5ae5cSThomas Moestl cur.dinfo->devices, 5135fc5ae5cSThomas Moestl num_devices, matches, 5145fc5ae5cSThomas Moestl num_matches, 5158d2fbde5SJustin T. Gibbs specified_devices, 5168d2fbde5SJustin T. Gibbs num_devices_specified, 5175fc5ae5cSThomas Moestl select_mode, maxshowdevs, 5185fc5ae5cSThomas Moestl hflag); 5198d2fbde5SJustin T. Gibbs switch(retval) { 5208d2fbde5SJustin T. Gibbs case -1: 5218d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 5228d2fbde5SJustin T. Gibbs break; 5238d2fbde5SJustin T. Gibbs case 1: 524775b0074SGuido van Rooij phdr(); 52553fbcd3aSGiorgos Keramidas if (wresized != 0) 52653fbcd3aSGiorgos Keramidas doresize(); 52753fbcd3aSGiorgos Keramidas headercount = wrows; 5288d2fbde5SJustin T. Gibbs break; 5298d2fbde5SJustin T. Gibbs default: 5308d2fbde5SJustin T. Gibbs break; 531dea673e9SRodney W. Grimes } 5328d2fbde5SJustin T. Gibbs break; 5338d2fbde5SJustin T. Gibbs } 5348d2fbde5SJustin T. Gibbs default: 5358d2fbde5SJustin T. Gibbs break; 5368d2fbde5SJustin T. Gibbs } 5378d2fbde5SJustin T. Gibbs 5388d2fbde5SJustin T. Gibbs /* 5398d2fbde5SJustin T. Gibbs * We only want to re-select devices if we're in 'top' 5408d2fbde5SJustin T. Gibbs * mode. This is the only mode where the devices selected 5418d2fbde5SJustin T. Gibbs * could actually change. 5428d2fbde5SJustin T. Gibbs */ 5438d2fbde5SJustin T. Gibbs if (hflag > 0) { 5448d2fbde5SJustin T. Gibbs int retval; 5455fc5ae5cSThomas Moestl retval = devstat_selectdevs(&dev_select, &num_selected, 5465fc5ae5cSThomas Moestl &num_selections, 5475fc5ae5cSThomas Moestl &select_generation, 5485fc5ae5cSThomas Moestl generation, 5495fc5ae5cSThomas Moestl cur.dinfo->devices, 5505fc5ae5cSThomas Moestl num_devices, matches, 5515fc5ae5cSThomas Moestl num_matches, 5528d2fbde5SJustin T. Gibbs specified_devices, 5538d2fbde5SJustin T. Gibbs num_devices_specified, 5545fc5ae5cSThomas Moestl select_mode, maxshowdevs, 5555fc5ae5cSThomas Moestl hflag); 5568d2fbde5SJustin T. Gibbs switch(retval) { 5578d2fbde5SJustin T. Gibbs case -1: 5588d2fbde5SJustin T. Gibbs errx(1,"%s", devstat_errbuf); 5598d2fbde5SJustin T. Gibbs break; 5608d2fbde5SJustin T. Gibbs case 1: 561775b0074SGuido van Rooij phdr(); 56253fbcd3aSGiorgos Keramidas if (wresized != 0) 56353fbcd3aSGiorgos Keramidas doresize(); 56453fbcd3aSGiorgos Keramidas headercount = wrows; 5658d2fbde5SJustin T. Gibbs break; 5668d2fbde5SJustin T. Gibbs default: 5678d2fbde5SJustin T. Gibbs break; 5688d2fbde5SJustin T. Gibbs } 5698d2fbde5SJustin T. Gibbs } 5708d2fbde5SJustin T. Gibbs 5715dc445bfSKenneth D. Merry if (Tflag > 0) { 572dea673e9SRodney W. Grimes tmp = cur.tk_nin; 573dea673e9SRodney W. Grimes cur.tk_nin -= last.tk_nin; 574dea673e9SRodney W. Grimes last.tk_nin = tmp; 575dea673e9SRodney W. Grimes tmp = cur.tk_nout; 576dea673e9SRodney W. Grimes cur.tk_nout -= last.tk_nout; 577dea673e9SRodney W. Grimes last.tk_nout = tmp; 578dea673e9SRodney W. Grimes } 5795dc445bfSKenneth D. Merry 5807194d335SPoul-Henning Kamp etime = cur.snap_time - last.snap_time; 5815dc445bfSKenneth D. Merry 582dea673e9SRodney W. Grimes if (etime == 0.0) 583dea673e9SRodney W. Grimes etime = 1.0; 5845dc445bfSKenneth D. Merry 5855dc445bfSKenneth D. Merry for (i = 0; i < CPUSTATES; i++) { 5865dc445bfSKenneth D. Merry tmp = cur.cp_time[i]; 5875dc445bfSKenneth D. Merry cur.cp_time[i] -= last.cp_time[i]; 5885dc445bfSKenneth D. Merry last.cp_time[i] = tmp; 5895dc445bfSKenneth D. Merry } 5905dc445bfSKenneth D. Merry 5916c359123SMaxim Konovalov if (xflag == 0 && Tflag > 0) 5925dc445bfSKenneth D. Merry printf("%4.0Lf %5.0Lf", cur.tk_nin / etime, 5938d2fbde5SJustin T. Gibbs cur.tk_nout / etime); 5945dc445bfSKenneth D. Merry 5955fc5ae5cSThomas Moestl devstats(hflag, etime, havelast); 5965dc445bfSKenneth D. Merry 5976c359123SMaxim Konovalov if (xflag == 0) { 5985dc445bfSKenneth D. Merry if (Cflag > 0) 599dea673e9SRodney W. Grimes cpustats(); 6005dc445bfSKenneth D. Merry 6018d2fbde5SJustin T. Gibbs printf("\n"); 6026c359123SMaxim Konovalov } 6038d2fbde5SJustin T. Gibbs fflush(stdout); 604dea673e9SRodney W. Grimes 6058d2fbde5SJustin T. Gibbs if (count >= 0 && --count <= 0) 606dea673e9SRodney W. Grimes break; 6078d2fbde5SJustin T. Gibbs 608*8b10473dSSean Bruno usleep(waittime * 1000); 6095fc5ae5cSThomas Moestl havelast = 1; 610dea673e9SRodney W. Grimes } 6118d2fbde5SJustin T. Gibbs 612dea673e9SRodney W. Grimes exit(0); 613dea673e9SRodney W. Grimes } 614dea673e9SRodney W. Grimes 615775b0074SGuido van Rooij /* 616775b0074SGuido van Rooij * Force a header to be prepended to the next output. 617775b0074SGuido van Rooij */ 618775b0074SGuido van Rooij void 619775b0074SGuido van Rooij needhdr(int signo) 620dea673e9SRodney W. Grimes { 621e65cded7SKris Kennaway 622775b0074SGuido van Rooij headercount = 1; 623e65cded7SKris Kennaway } 624e65cded7SKris Kennaway 62553fbcd3aSGiorgos Keramidas /* 62653fbcd3aSGiorgos Keramidas * When the terminal is resized, force an update of the maximum number of rows 62753fbcd3aSGiorgos Keramidas * printed between each header repetition. Then force a new header to be 62853fbcd3aSGiorgos Keramidas * prepended to the next output. 62953fbcd3aSGiorgos Keramidas */ 63053fbcd3aSGiorgos Keramidas void 63153fbcd3aSGiorgos Keramidas needresize(int signo) 63253fbcd3aSGiorgos Keramidas { 63353fbcd3aSGiorgos Keramidas 63453fbcd3aSGiorgos Keramidas wresized = 1; 63553fbcd3aSGiorgos Keramidas headercount = 1; 63653fbcd3aSGiorgos Keramidas } 63753fbcd3aSGiorgos Keramidas 63853fbcd3aSGiorgos Keramidas /* 63953fbcd3aSGiorgos Keramidas * Update the global `wrows' count of terminal rows. 64053fbcd3aSGiorgos Keramidas */ 64153fbcd3aSGiorgos Keramidas void 64253fbcd3aSGiorgos Keramidas doresize(void) 64353fbcd3aSGiorgos Keramidas { 64453fbcd3aSGiorgos Keramidas int status; 64553fbcd3aSGiorgos Keramidas struct winsize w; 64653fbcd3aSGiorgos Keramidas 64753fbcd3aSGiorgos Keramidas for (;;) { 64853fbcd3aSGiorgos Keramidas status = ioctl(fileno(stdout), TIOCGWINSZ, &w); 64953fbcd3aSGiorgos Keramidas if (status == -1 && errno == EINTR) 65053fbcd3aSGiorgos Keramidas continue; 65153fbcd3aSGiorgos Keramidas else if (status == -1) 65253fbcd3aSGiorgos Keramidas err(1, "ioctl"); 65353fbcd3aSGiorgos Keramidas if (w.ws_row > 3) 65453fbcd3aSGiorgos Keramidas wrows = w.ws_row - 3; 65553fbcd3aSGiorgos Keramidas else 65653fbcd3aSGiorgos Keramidas wrows = IOSTAT_DEFAULT_ROWS; 65753fbcd3aSGiorgos Keramidas break; 65853fbcd3aSGiorgos Keramidas } 65953fbcd3aSGiorgos Keramidas 66053fbcd3aSGiorgos Keramidas /* 66153fbcd3aSGiorgos Keramidas * Inhibit doresize() calls until we are rescheduled by SIGWINCH. 66253fbcd3aSGiorgos Keramidas */ 66353fbcd3aSGiorgos Keramidas wresized = 0; 66453fbcd3aSGiorgos Keramidas } 66553fbcd3aSGiorgos Keramidas 666e65cded7SKris Kennaway static void 667775b0074SGuido van Rooij phdr(void) 668e65cded7SKris Kennaway { 66947e065b4SMaxim Konovalov int i, printed; 670ab8ac08eSAdrian Chadd char devbuf[256]; 671dea673e9SRodney W. Grimes 6726c359123SMaxim Konovalov /* 6736c359123SMaxim Konovalov * If xflag is set, we need a per-loop header, not a page header, so 6746c359123SMaxim Konovalov * just return. We'll print the header in devstats(). 6756c359123SMaxim Konovalov */ 6766c359123SMaxim Konovalov if (xflag > 0) 6776c359123SMaxim Konovalov return; 6786c359123SMaxim Konovalov 6795dc445bfSKenneth D. Merry if (Tflag > 0) 680dea673e9SRodney W. Grimes (void)printf(" tty"); 6818d2fbde5SJustin T. Gibbs for (i = 0, printed=0;(i < num_devices) && (printed < maxshowdevs);i++){ 6828d2fbde5SJustin T. Gibbs int di; 6838d2fbde5SJustin T. Gibbs if ((dev_select[i].selected != 0) 6848d2fbde5SJustin T. Gibbs && (dev_select[i].selected <= maxshowdevs)) { 6858d2fbde5SJustin T. Gibbs di = dev_select[i].position; 686ab8ac08eSAdrian Chadd snprintf(devbuf, sizeof(devbuf), "%s%d", 687ab8ac08eSAdrian Chadd cur.dinfo->devices[di].device_name, 688ab8ac08eSAdrian Chadd cur.dinfo->devices[di].unit_number); 6898d2fbde5SJustin T. Gibbs if (oflag > 0) 690ab8ac08eSAdrian Chadd (void)printf("%13.6s ", devbuf); 6918d2fbde5SJustin T. Gibbs else 692ab8ac08eSAdrian Chadd printf("%16.6s ", devbuf); 6938d2fbde5SJustin T. Gibbs printed++; 6948d2fbde5SJustin T. Gibbs } 6958d2fbde5SJustin T. Gibbs } 6965dc445bfSKenneth D. Merry if (Cflag > 0) 6978d2fbde5SJustin T. Gibbs (void)printf(" cpu\n"); 6988d2fbde5SJustin T. Gibbs else 6998d2fbde5SJustin T. Gibbs (void)printf("\n"); 7008d2fbde5SJustin T. Gibbs 7015dc445bfSKenneth D. Merry if (Tflag > 0) 7028d2fbde5SJustin T. Gibbs (void)printf(" tin tout"); 7038d2fbde5SJustin T. Gibbs 7048d2fbde5SJustin T. Gibbs for (i=0, printed = 0;(i < num_devices) && (printed < maxshowdevs);i++){ 7058d2fbde5SJustin T. Gibbs if ((dev_select[i].selected != 0) 7068d2fbde5SJustin T. Gibbs && (dev_select[i].selected <= maxshowdevs)) { 7072fa4aaa0SMatthew Dillon if (oflag > 0) { 7088d2fbde5SJustin T. Gibbs if (Iflag == 0) 709dea673e9SRodney W. Grimes (void)printf(" sps tps msps "); 7108d2fbde5SJustin T. Gibbs else 7118d2fbde5SJustin T. Gibbs (void)printf(" blk xfr msps "); 7122fa4aaa0SMatthew Dillon } else { 7138d2fbde5SJustin T. Gibbs if (Iflag == 0) 7148d2fbde5SJustin T. Gibbs printf(" KB/t tps MB/s "); 7158d2fbde5SJustin T. Gibbs else 7168d2fbde5SJustin T. Gibbs printf(" KB/t xfrs MB "); 7172fa4aaa0SMatthew Dillon } 7188d2fbde5SJustin T. Gibbs printed++; 7198d2fbde5SJustin T. Gibbs } 7208d2fbde5SJustin T. Gibbs } 7215dc445bfSKenneth D. Merry if (Cflag > 0) 722936d754aSAndrey A. Chernov (void)printf(" us ni sy in id\n"); 7238d2fbde5SJustin T. Gibbs else 7248d2fbde5SJustin T. Gibbs printf("\n"); 725775b0074SGuido van Rooij 726dea673e9SRodney W. Grimes } 727dea673e9SRodney W. Grimes 7288d2fbde5SJustin T. Gibbs static void 7295dc445bfSKenneth D. Merry devstats(int perf_select, long double etime, int havelast) 730dea673e9SRodney W. Grimes { 73147e065b4SMaxim Konovalov int dn; 7326c359123SMaxim Konovalov long double transfers_per_second, transfers_per_second_read, transfers_per_second_write; 7336c359123SMaxim Konovalov long double kb_per_transfer, mb_per_second, mb_per_second_read, mb_per_second_write; 7348d2fbde5SJustin T. Gibbs u_int64_t total_bytes, total_transfers, total_blocks; 73530ff1266SMaxim Konovalov u_int64_t total_bytes_read, total_transfers_read; 73630ff1266SMaxim Konovalov u_int64_t total_bytes_write, total_transfers_write; 7376c359123SMaxim Konovalov long double busy_pct; 7386c359123SMaxim Konovalov u_int64_t queue_len; 7398d2fbde5SJustin T. Gibbs long double total_mb; 7408d2fbde5SJustin T. Gibbs long double blocks_per_second, ms_per_transaction; 7416c359123SMaxim Konovalov int firstline = 1; 7426c359123SMaxim Konovalov char *devname; 7436c359123SMaxim Konovalov 7446c359123SMaxim Konovalov if (xflag > 0) { 7456c359123SMaxim Konovalov printf(" extended device statistics "); 7466c359123SMaxim Konovalov if (Tflag > 0) 7476c359123SMaxim Konovalov printf(" tty "); 7486c359123SMaxim Konovalov if (Cflag > 0) 7496c359123SMaxim Konovalov printf(" cpu "); 7506c359123SMaxim Konovalov printf("\n"); 75130ff1266SMaxim Konovalov if (Iflag == 0) 752beda5f78SMaxim Konovalov printf( 7535b68ad55SMaxim Konovalov "device r/s w/s kr/s kw/s wait svc_t %%b " 754beda5f78SMaxim Konovalov ); 75530ff1266SMaxim Konovalov else 756beda5f78SMaxim Konovalov printf( 7575b68ad55SMaxim Konovalov "device r/i w/i kr/i kw/i wait svc_t %%b " 758beda5f78SMaxim Konovalov ); 7596c359123SMaxim Konovalov if (Tflag > 0) 7606c359123SMaxim Konovalov printf("tin tout "); 7616c359123SMaxim Konovalov if (Cflag > 0) 7626c359123SMaxim Konovalov printf("us ni sy in id "); 7636c359123SMaxim Konovalov printf("\n"); 7646c359123SMaxim Konovalov } 765dea673e9SRodney W. Grimes 7668d2fbde5SJustin T. Gibbs for (dn = 0; dn < num_devices; dn++) { 7678d2fbde5SJustin T. Gibbs int di; 7688d2fbde5SJustin T. Gibbs 7698d2fbde5SJustin T. Gibbs if (((perf_select == 0) && (dev_select[dn].selected == 0)) 7708d2fbde5SJustin T. Gibbs || (dev_select[dn].selected > maxshowdevs)) 771dea673e9SRodney W. Grimes continue; 772dea673e9SRodney W. Grimes 7738d2fbde5SJustin T. Gibbs di = dev_select[dn].position; 774dea673e9SRodney W. Grimes 7755fc5ae5cSThomas Moestl if (devstat_compute_statistics(&cur.dinfo->devices[di], 7765dc445bfSKenneth D. Merry havelast ? &last.dinfo->devices[di] : NULL, etime, 7775fc5ae5cSThomas Moestl DSM_TOTAL_BYTES, &total_bytes, 77830ff1266SMaxim Konovalov DSM_TOTAL_BYTES_READ, &total_bytes_read, 77930ff1266SMaxim Konovalov DSM_TOTAL_BYTES_WRITE, &total_bytes_write, 7805fc5ae5cSThomas Moestl DSM_TOTAL_TRANSFERS, &total_transfers, 78130ff1266SMaxim Konovalov DSM_TOTAL_TRANSFERS_READ, &total_transfers_read, 78230ff1266SMaxim Konovalov DSM_TOTAL_TRANSFERS_WRITE, &total_transfers_write, 7835fc5ae5cSThomas Moestl DSM_TOTAL_BLOCKS, &total_blocks, 7845fc5ae5cSThomas Moestl DSM_KB_PER_TRANSFER, &kb_per_transfer, 7855fc5ae5cSThomas Moestl DSM_TRANSFERS_PER_SECOND, &transfers_per_second, 7866c359123SMaxim Konovalov DSM_TRANSFERS_PER_SECOND_READ, &transfers_per_second_read, 7876c359123SMaxim Konovalov DSM_TRANSFERS_PER_SECOND_WRITE, &transfers_per_second_write, 7885fc5ae5cSThomas Moestl DSM_MB_PER_SECOND, &mb_per_second, 7896c359123SMaxim Konovalov DSM_MB_PER_SECOND_READ, &mb_per_second_read, 7906c359123SMaxim Konovalov DSM_MB_PER_SECOND_WRITE, &mb_per_second_write, 7915fc5ae5cSThomas Moestl DSM_BLOCKS_PER_SECOND, &blocks_per_second, 7925fc5ae5cSThomas Moestl DSM_MS_PER_TRANSACTION, &ms_per_transaction, 7936c359123SMaxim Konovalov DSM_BUSY_PCT, &busy_pct, 7946c359123SMaxim Konovalov DSM_QUEUE_LENGTH, &queue_len, 7955fc5ae5cSThomas Moestl DSM_NONE) != 0) 7968d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 7978d2fbde5SJustin T. Gibbs 7988d2fbde5SJustin T. Gibbs if (perf_select != 0) { 7998d2fbde5SJustin T. Gibbs dev_select[dn].bytes = total_bytes; 8008d2fbde5SJustin T. Gibbs if ((dev_select[dn].selected == 0) 8018d2fbde5SJustin T. Gibbs || (dev_select[dn].selected > maxshowdevs)) 8028d2fbde5SJustin T. Gibbs continue; 8038d2fbde5SJustin T. Gibbs } 8048d2fbde5SJustin T. Gibbs 8056c359123SMaxim Konovalov if (Kflag > 0 || xflag > 0) { 8062fa4aaa0SMatthew Dillon int block_size = cur.dinfo->devices[di].block_size; 807e4d7fe02SKenneth D. Merry total_blocks = total_blocks * (block_size ? 808e4d7fe02SKenneth D. Merry block_size : 512) / 1024; 8092fa4aaa0SMatthew Dillon } 8102fa4aaa0SMatthew Dillon 8116c359123SMaxim Konovalov if (xflag > 0) { 81238992545SMaxim Konovalov if (asprintf(&devname, "%s%d", 8136c359123SMaxim Konovalov cur.dinfo->devices[di].device_name, 814e08b1089SMaxim Konovalov cur.dinfo->devices[di].unit_number) == -1) 815e08b1089SMaxim Konovalov err(1, "asprintf"); 8166c359123SMaxim Konovalov /* 8176c359123SMaxim Konovalov * If zflag is set, skip any devices with zero I/O. 8186c359123SMaxim Konovalov */ 8196c359123SMaxim Konovalov if (zflag == 0 || transfers_per_second_read > 0.05 || 8206c359123SMaxim Konovalov transfers_per_second_write > 0.05 || 8216c359123SMaxim Konovalov mb_per_second_read > ((long double).0005)/1024 || 8226c359123SMaxim Konovalov mb_per_second_write > ((long double).0005)/1024 || 8236c359123SMaxim Konovalov busy_pct > 0.5) { 82430ff1266SMaxim Konovalov if (Iflag == 0) 8256c359123SMaxim Konovalov printf("%-8.8s %5.1Lf %5.1Lf %7.1Lf %7.1Lf %4qu %5.1Lf %3.0Lf ", 8266c359123SMaxim Konovalov devname, transfers_per_second_read, 8276c359123SMaxim Konovalov transfers_per_second_write, 8286c359123SMaxim Konovalov mb_per_second_read * 1024, 829fbe4fc2eSMaxim Konovalov mb_per_second_write * 1024, 830fbe4fc2eSMaxim Konovalov queue_len, 8316c359123SMaxim Konovalov ms_per_transaction, busy_pct); 83230ff1266SMaxim Konovalov else 83330ff1266SMaxim Konovalov printf("%-8.8s %5.1Lf %5.1Lf %7.1Lf %7.1Lf %4qu %5.1Lf %3.0Lf ", 834fbe4fc2eSMaxim Konovalov devname, 835fbe4fc2eSMaxim Konovalov (long double)total_transfers_read, 83630ff1266SMaxim Konovalov (long double)total_transfers_write, 837fbe4fc2eSMaxim Konovalov (long double) 838fbe4fc2eSMaxim Konovalov total_bytes_read / 1024, 839fbe4fc2eSMaxim Konovalov (long double) 840fbe4fc2eSMaxim Konovalov total_bytes_write / 1024, 841fbe4fc2eSMaxim Konovalov queue_len, 84230ff1266SMaxim Konovalov ms_per_transaction, busy_pct); 8436c359123SMaxim Konovalov if (firstline) { 8446c359123SMaxim Konovalov /* 8456c359123SMaxim Konovalov * If this is the first device 8466c359123SMaxim Konovalov * we're printing, also print 8476c359123SMaxim Konovalov * CPU or TTY stats if requested. 8486c359123SMaxim Konovalov */ 8496c359123SMaxim Konovalov firstline = 0; 8506c359123SMaxim Konovalov if (Tflag > 0) 8516c359123SMaxim Konovalov printf("%4.0Lf%5.0Lf", 8526c359123SMaxim Konovalov cur.tk_nin / etime, 8536c359123SMaxim Konovalov cur.tk_nout / etime); 8546c359123SMaxim Konovalov if (Cflag > 0) 8556c359123SMaxim Konovalov cpustats(); 8566c359123SMaxim Konovalov } 8576c359123SMaxim Konovalov printf("\n"); 8586c359123SMaxim Konovalov } 85938992545SMaxim Konovalov free(devname); 8606c359123SMaxim Konovalov } else if (oflag > 0) { 8612fa4aaa0SMatthew Dillon int msdig = (ms_per_transaction < 100.0) ? 1 : 0; 8628d2fbde5SJustin T. Gibbs 8638d2fbde5SJustin T. Gibbs if (Iflag == 0) 8642fa4aaa0SMatthew Dillon printf("%4.0Lf%4.0Lf%5.*Lf ", 8658d2fbde5SJustin T. Gibbs blocks_per_second, 8668d2fbde5SJustin T. Gibbs transfers_per_second, 8672fa4aaa0SMatthew Dillon msdig, 8688d2fbde5SJustin T. Gibbs ms_per_transaction); 869dea673e9SRodney W. Grimes else 8702fa4aaa0SMatthew Dillon printf("%4.1qu%4.1qu%5.*Lf ", 8718d2fbde5SJustin T. Gibbs total_blocks, 8728d2fbde5SJustin T. Gibbs total_transfers, 8732fa4aaa0SMatthew Dillon msdig, 8748d2fbde5SJustin T. Gibbs ms_per_transaction); 8758d2fbde5SJustin T. Gibbs } else { 8768d2fbde5SJustin T. Gibbs if (Iflag == 0) 8778d2fbde5SJustin T. Gibbs printf(" %5.2Lf %3.0Lf %5.2Lf ", 8788d2fbde5SJustin T. Gibbs kb_per_transfer, 8798d2fbde5SJustin T. Gibbs transfers_per_second, 8808d2fbde5SJustin T. Gibbs mb_per_second); 8818d2fbde5SJustin T. Gibbs else { 8828d2fbde5SJustin T. Gibbs total_mb = total_bytes; 8838d2fbde5SJustin T. Gibbs total_mb /= 1024 * 1024; 8848d2fbde5SJustin T. Gibbs 8858d2fbde5SJustin T. Gibbs printf(" %5.2Lf %3.1qu %5.2Lf ", 8868d2fbde5SJustin T. Gibbs kb_per_transfer, 8878d2fbde5SJustin T. Gibbs total_transfers, 8888d2fbde5SJustin T. Gibbs total_mb); 8898d2fbde5SJustin T. Gibbs } 8908d2fbde5SJustin T. Gibbs } 891dea673e9SRodney W. Grimes } 8926c359123SMaxim Konovalov if (xflag > 0 && zflag > 0 && firstline == 1 && 8936c359123SMaxim Konovalov (Tflag > 0 || Cflag > 0)) { 8946c359123SMaxim Konovalov /* 8956c359123SMaxim Konovalov * If zflag is set and we did not print any device 8966c359123SMaxim Konovalov * lines I/O because they were all zero, 8976c359123SMaxim Konovalov * print TTY/CPU stats. 8986c359123SMaxim Konovalov */ 8996c359123SMaxim Konovalov printf("%52s",""); 9006c359123SMaxim Konovalov if (Tflag > 0) 9016c359123SMaxim Konovalov printf("%4.0Lf %5.0Lf", cur.tk_nin / etime, 9026c359123SMaxim Konovalov cur.tk_nout / etime); 9036c359123SMaxim Konovalov if (Cflag > 0) 9046c359123SMaxim Konovalov cpustats(); 9056c359123SMaxim Konovalov printf("\n"); 9066c359123SMaxim Konovalov } 907dea673e9SRodney W. Grimes } 908dea673e9SRodney W. Grimes 9098d2fbde5SJustin T. Gibbs static void 9108d2fbde5SJustin T. Gibbs cpustats(void) 911dea673e9SRodney W. Grimes { 91247e065b4SMaxim Konovalov int state; 913dea673e9SRodney W. Grimes double time; 914dea673e9SRodney W. Grimes 9158d2fbde5SJustin T. Gibbs time = 0.0; 9168d2fbde5SJustin T. Gibbs 917dea673e9SRodney W. Grimes for (state = 0; state < CPUSTATES; ++state) 918dea673e9SRodney W. Grimes time += cur.cp_time[state]; 919dea673e9SRodney W. Grimes for (state = 0; state < CPUSTATES; ++state) 9208fa6b8a8SBruce Evans printf(" %2.0f", 9215dc445bfSKenneth D. Merry rint(100. * cur.cp_time[state] / (time ? time : 1))); 922dea673e9SRodney W. Grimes } 9235fc5ae5cSThomas Moestl 9245dc445bfSKenneth D. Merry static int 9255dc445bfSKenneth D. Merry readvar(kvm_t *kd, const char *name, int nlid, void *ptr, size_t len) 9265fc5ae5cSThomas Moestl { 9275dc445bfSKenneth D. Merry if (kd != NULL) { 9285dc445bfSKenneth D. Merry ssize_t nbytes; 9295dc445bfSKenneth D. Merry 9308d56a4caSJohn Baldwin nbytes = kvm_read(kd, namelist[nlid].n_value, ptr, len); 9315dc445bfSKenneth D. Merry 9328d56a4caSJohn Baldwin if (nbytes < 0) { 9338d56a4caSJohn Baldwin warnx("kvm_read(%s): %s", namelist[nlid].n_name, 9348d56a4caSJohn Baldwin kvm_geterr(kd)); 9355dc445bfSKenneth D. Merry return (1); 9365dc445bfSKenneth D. Merry } 9375dc445bfSKenneth D. Merry if (nbytes != len) { 9388d56a4caSJohn Baldwin warnx("kvm_read(%s): expected %zu bytes, got %zd bytes", 9398d56a4caSJohn Baldwin namelist[nlid].n_name, len, nbytes); 9405dc445bfSKenneth D. Merry return (1); 9415dc445bfSKenneth D. Merry } 9425dc445bfSKenneth D. Merry } else { 9435fc5ae5cSThomas Moestl size_t nlen = len; 9445fc5ae5cSThomas Moestl 9455dc445bfSKenneth D. Merry if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) { 9465dc445bfSKenneth D. Merry warn("sysctl(%s...) failed", name); 9475dc445bfSKenneth D. Merry return (1); 9485dc445bfSKenneth D. Merry } 9495dc445bfSKenneth D. Merry if (nlen != len) { 9505dc445bfSKenneth D. Merry warnx("sysctl(%s...): expected %lu, got %lu", name, 9515fc5ae5cSThomas Moestl (unsigned long)len, (unsigned long)nlen); 9525dc445bfSKenneth D. Merry return (1); 9535dc445bfSKenneth D. Merry } 9545dc445bfSKenneth D. Merry } 9555dc445bfSKenneth D. Merry return (0); 9565fc5ae5cSThomas Moestl } 957