18a16b7a1SPedro F. Giffuni /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 45dc445bfSKenneth D. Merry * Copyright (c) 1997, 1998, 2000, 2001 Kenneth D. Merry 58d2fbde5SJustin T. Gibbs * All rights reserved. 68d2fbde5SJustin T. Gibbs * 78d2fbde5SJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 88d2fbde5SJustin T. Gibbs * modification, are permitted provided that the following conditions 98d2fbde5SJustin T. Gibbs * are met: 108d2fbde5SJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 118d2fbde5SJustin T. Gibbs * notice, this list of conditions and the following disclaimer. 128d2fbde5SJustin T. Gibbs * 2. Redistributions in binary form must reproduce the above copyright 138d2fbde5SJustin T. Gibbs * notice, this list of conditions and the following disclaimer in the 148d2fbde5SJustin T. Gibbs * documentation and/or other materials provided with the distribution. 158d2fbde5SJustin T. Gibbs * 3. The name of the author may not be used to endorse or promote products 168d2fbde5SJustin T. Gibbs * derived from this software without specific prior written permission. 178d2fbde5SJustin T. Gibbs * 188d2fbde5SJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 198d2fbde5SJustin T. Gibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 208d2fbde5SJustin T. Gibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 218d2fbde5SJustin T. Gibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 228d2fbde5SJustin T. Gibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 238d2fbde5SJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 248d2fbde5SJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 258d2fbde5SJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 268d2fbde5SJustin T. Gibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 278d2fbde5SJustin T. Gibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 288d2fbde5SJustin T. Gibbs * SUCH DAMAGE. 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 * 4. Neither the name of the University nor the names of its contributors 47dea673e9SRodney W. Grimes * may be used to endorse or promote products derived from this software 48dea673e9SRodney W. Grimes * without specific prior written permission. 49dea673e9SRodney W. Grimes * 50dea673e9SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 51dea673e9SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52dea673e9SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53dea673e9SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 54dea673e9SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55dea673e9SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56dea673e9SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57dea673e9SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58dea673e9SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59dea673e9SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60dea673e9SRodney W. Grimes * SUCH DAMAGE. 61dea673e9SRodney W. Grimes */ 628d2fbde5SJustin T. Gibbs /* 638d2fbde5SJustin T. Gibbs * Ideas for the new iostat statistics output modes taken from the NetBSD 648d2fbde5SJustin T. Gibbs * version of iostat: 658d2fbde5SJustin T. Gibbs */ 668d2fbde5SJustin T. Gibbs /* 678d2fbde5SJustin T. Gibbs * Copyright (c) 1996 John M. Vinopal 688d2fbde5SJustin T. Gibbs * All rights reserved. 698d2fbde5SJustin T. Gibbs * 708d2fbde5SJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 718d2fbde5SJustin T. Gibbs * modification, are permitted provided that the following conditions 728d2fbde5SJustin T. Gibbs * are met: 738d2fbde5SJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 748d2fbde5SJustin T. Gibbs * notice, this list of conditions and the following disclaimer. 758d2fbde5SJustin T. Gibbs * 2. Redistributions in binary form must reproduce the above copyright 768d2fbde5SJustin T. Gibbs * notice, this list of conditions and the following disclaimer in the 778d2fbde5SJustin T. Gibbs * documentation and/or other materials provided with the distribution. 788d2fbde5SJustin T. Gibbs * 3. All advertising materials mentioning features or use of this software 798d2fbde5SJustin T. Gibbs * must display the following acknowledgement: 808d2fbde5SJustin T. Gibbs * This product includes software developed for the NetBSD Project 818d2fbde5SJustin T. Gibbs * by John M. Vinopal. 828d2fbde5SJustin T. Gibbs * 4. The name of the author may not be used to endorse or promote products 838d2fbde5SJustin T. Gibbs * derived from this software without specific prior written permission. 848d2fbde5SJustin T. Gibbs * 858d2fbde5SJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 868d2fbde5SJustin T. Gibbs * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 878d2fbde5SJustin T. Gibbs * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 888d2fbde5SJustin T. Gibbs * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 898d2fbde5SJustin T. Gibbs * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 908d2fbde5SJustin T. Gibbs * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 918d2fbde5SJustin T. Gibbs * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 928d2fbde5SJustin T. Gibbs * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 938d2fbde5SJustin T. Gibbs * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 948d2fbde5SJustin T. Gibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 958d2fbde5SJustin T. Gibbs * SUCH DAMAGE. 968d2fbde5SJustin T. Gibbs */ 97dea673e9SRodney W. Grimes 98dea673e9SRodney W. Grimes 99dea673e9SRodney W. Grimes #include <sys/param.h> 1008d2fbde5SJustin T. Gibbs #include <sys/errno.h> 101190ff54eSPoul-Henning Kamp #include <sys/resource.h> 1025fc5ae5cSThomas Moestl #include <sys/sysctl.h> 103dea673e9SRodney W. Grimes 104dea673e9SRodney W. Grimes #include <ctype.h> 105cfed15e6SDimitry Andric #include <devstat.h> 106cfed15e6SDimitry Andric #include <err.h> 107dea673e9SRodney W. Grimes #include <fcntl.h> 108cfed15e6SDimitry Andric #include <inttypes.h> 109dea673e9SRodney W. Grimes #include <kvm.h> 110cfed15e6SDimitry Andric #include <limits.h> 111cfed15e6SDimitry Andric #include <math.h> 1122757068eSBruce Evans #include <nlist.h> 113da61e79cSAlan Somers #include <signal.h> 114dea673e9SRodney W. Grimes #include <stdio.h> 115dea673e9SRodney W. Grimes #include <stdlib.h> 116dea673e9SRodney W. Grimes #include <string.h> 11753fbcd3aSGiorgos Keramidas #include <termios.h> 118dea673e9SRodney W. Grimes #include <unistd.h> 119dea673e9SRodney W. Grimes 120a59c2129SAlan Somers static struct nlist namelist[] = { 1218cb3704aSSergey Kandaurov #define X_TTY_NIN 0 122a59c2129SAlan Somers { .n_name = "_tty_nin", 123a59c2129SAlan Somers .n_type = 0, .n_other = 0, .n_desc = 0, .n_value = 0 }, 1248cb3704aSSergey Kandaurov #define X_TTY_NOUT 1 125a59c2129SAlan Somers { .n_name = "_tty_nout", 126a59c2129SAlan Somers .n_type = 0, .n_other = 0, .n_desc = 0, .n_value = 0 }, 12732c9e3bdSJohn Baldwin #define X_BOOTTIME 2 128a59c2129SAlan Somers { .n_name = "_boottime", 129a59c2129SAlan Somers .n_type = 0, .n_other = 0, .n_desc = 0, .n_value = 0 }, 13032c9e3bdSJohn Baldwin #define X_END 2 131a59c2129SAlan Somers { .n_name = NULL, 132a59c2129SAlan Somers .n_type = 0, .n_other = 0, .n_desc = 0, .n_value = 0 }, 133dea673e9SRodney W. Grimes }; 134dea673e9SRodney W. Grimes 13553fbcd3aSGiorgos Keramidas #define IOSTAT_DEFAULT_ROWS 20 /* Traditional default `wrows' */ 13653fbcd3aSGiorgos Keramidas 137a59c2129SAlan Somers static struct statinfo cur, last; 138a59c2129SAlan Somers static int num_devices; 139a59c2129SAlan Somers static struct device_selection *dev_select; 140a59c2129SAlan Somers static int maxshowdevs; 141a59c2129SAlan Somers static volatile sig_atomic_t headercount; 142a59c2129SAlan Somers static volatile sig_atomic_t wresized; /* Tty resized, when non-zero. */ 143a59c2129SAlan Somers static volatile sig_atomic_t alarm_rang; 144a59c2129SAlan Somers static volatile sig_atomic_t return_requested; 145a59c2129SAlan Somers static unsigned short wrows; /* Current number of tty rows. */ 146a59c2129SAlan Somers static int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0; 147a59c2129SAlan Somers static int xflag = 0, zflag = 0; 148dea673e9SRodney W. Grimes 1498d2fbde5SJustin T. Gibbs /* local function declarations */ 150a9cce232SAlfonso Gregory static void usage(void) __dead2; 151775b0074SGuido van Rooij static void needhdr(int signo); 15253fbcd3aSGiorgos Keramidas static void needresize(int signo); 153da61e79cSAlan Somers static void needreturn(int signo); 154da61e79cSAlan Somers static void alarm_clock(int signo); 15553fbcd3aSGiorgos Keramidas static void doresize(void); 156775b0074SGuido van Rooij static void phdr(void); 1575dc445bfSKenneth D. Merry static void devstats(int perf_select, long double etime, int havelast); 1588d2fbde5SJustin T. Gibbs static void cpustats(void); 1595dc445bfSKenneth D. Merry static int readvar(kvm_t *kd, const char *name, int nlid, void *ptr, 1605dc445bfSKenneth D. Merry size_t len); 161dea673e9SRodney W. Grimes 1628d2fbde5SJustin T. Gibbs static void 1638d2fbde5SJustin T. Gibbs usage(void) 1648d2fbde5SJustin T. Gibbs { 1658d2fbde5SJustin T. Gibbs /* 1668d2fbde5SJustin T. Gibbs * We also support the following 'traditional' syntax: 1678d2fbde5SJustin T. Gibbs * iostat [drives] [wait [count]] 1688d2fbde5SJustin T. Gibbs * This isn't mentioned in the man page, or the usage statement, 1698d2fbde5SJustin T. Gibbs * but it is supported. 1708d2fbde5SJustin T. Gibbs */ 17109c45b08SDag-Erling Smørgrav fprintf(stderr, "usage: iostat [-CdhIKoTxz] [-c count] [-M core]" 1728743d3dcSPhilippe Charnier " [-n devs] [-N system]\n" 1738743d3dcSPhilippe Charnier "\t [-t type,if,pass] [-w wait] [drives]\n"); 174a9cce232SAlfonso Gregory exit(1); 1758d2fbde5SJustin T. Gibbs } 176dea673e9SRodney W. Grimes 177dea673e9SRodney W. Grimes int 1788d2fbde5SJustin T. Gibbs main(int argc, char **argv) 179dea673e9SRodney W. Grimes { 18047e065b4SMaxim Konovalov int c, i; 18180badfcbSJohn Baldwin int hflag = 0, cflag = 0, wflag = 0, nflag = 0; 1828d2fbde5SJustin T. Gibbs int count = 0, waittime = 0; 1838d2fbde5SJustin T. Gibbs char *memf = NULL, *nlistf = NULL; 1848d2fbde5SJustin T. Gibbs struct devstat_match *matches; 185da61e79cSAlan Somers struct itimerval alarmspec; 1868d2fbde5SJustin T. Gibbs int num_matches = 0; 187dea673e9SRodney W. Grimes char errbuf[_POSIX2_LINE_MAX]; 1885fc5ae5cSThomas Moestl kvm_t *kd = NULL; 189bcc6a3daSKenneth D. Merry long generation; 1908d2fbde5SJustin T. Gibbs int num_devices_specified; 191bcc6a3daSKenneth D. Merry int num_selected, num_selections; 192bcc6a3daSKenneth D. Merry long select_generation; 1938d2fbde5SJustin T. Gibbs char **specified_devices; 1948d2fbde5SJustin T. Gibbs devstat_select_mode select_mode; 1958b10473dSSean Bruno float f; 1965dc445bfSKenneth D. Merry int havelast = 0; 197dea673e9SRodney W. Grimes 1988d2fbde5SJustin T. Gibbs matches = NULL; 1998d2fbde5SJustin T. Gibbs maxshowdevs = 3; 2008d2fbde5SJustin T. Gibbs 20109c45b08SDag-Erling Smørgrav while ((c = getopt(argc, argv, "Cc:dhIKM:N:n:oTt:w:xz")) != -1) { 2028d2fbde5SJustin T. Gibbs switch (c) { 20309c45b08SDag-Erling Smørgrav case 'C': 20409c45b08SDag-Erling Smørgrav Cflag++; 20509c45b08SDag-Erling Smørgrav break; 206dea673e9SRodney W. Grimes case 'c': 2078d2fbde5SJustin T. Gibbs cflag++; 2088d2fbde5SJustin T. Gibbs count = atoi(optarg); 2098d2fbde5SJustin T. Gibbs if (count < 1) 2108d2fbde5SJustin T. Gibbs errx(1, "count %d is < 1", count); 2118d2fbde5SJustin T. Gibbs break; 2128d2fbde5SJustin T. Gibbs case 'd': 2138d2fbde5SJustin T. Gibbs dflag++; 2148d2fbde5SJustin T. Gibbs break; 2158d2fbde5SJustin T. Gibbs case 'h': 2168d2fbde5SJustin T. Gibbs hflag++; 2178d2fbde5SJustin T. Gibbs break; 2188d2fbde5SJustin T. Gibbs case 'I': 2198d2fbde5SJustin T. Gibbs Iflag++; 220dea673e9SRodney W. Grimes break; 221e4d7fe02SKenneth D. Merry case 'K': 222e4d7fe02SKenneth D. Merry Kflag++; 223e4d7fe02SKenneth D. Merry break; 224dea673e9SRodney W. Grimes case 'M': 225dea673e9SRodney W. Grimes memf = optarg; 226dea673e9SRodney W. Grimes break; 22709c45b08SDag-Erling Smørgrav case 'N': 22809c45b08SDag-Erling Smørgrav nlistf = optarg; 22909c45b08SDag-Erling Smørgrav break; 2308d2fbde5SJustin T. Gibbs case 'n': 2318d2fbde5SJustin T. Gibbs nflag++; 2328d2fbde5SJustin T. Gibbs maxshowdevs = atoi(optarg); 2338d2fbde5SJustin T. Gibbs if (maxshowdevs < 0) 2345d4a8fa9SPhilippe Charnier errx(1, "number of devices %d is < 0", 2358d2fbde5SJustin T. Gibbs maxshowdevs); 2368d2fbde5SJustin T. Gibbs break; 2378d2fbde5SJustin T. Gibbs case 'o': 2388d2fbde5SJustin T. Gibbs oflag++; 239dea673e9SRodney W. Grimes break; 24009c45b08SDag-Erling Smørgrav case 'T': 24109c45b08SDag-Erling Smørgrav Tflag++; 24209c45b08SDag-Erling Smørgrav break; 2438d2fbde5SJustin T. Gibbs case 't': 2445fc5ae5cSThomas Moestl if (devstat_buildmatch(optarg, &matches, 2458d2fbde5SJustin T. Gibbs &num_matches) != 0) 2468d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 2478d2fbde5SJustin T. Gibbs break; 2488d2fbde5SJustin T. Gibbs case 'w': 2498d2fbde5SJustin T. Gibbs wflag++; 2508b10473dSSean Bruno f = atof(optarg); 2518b10473dSSean Bruno waittime = f * 1000; 2528d2fbde5SJustin T. Gibbs if (waittime < 1) 2538b10473dSSean Bruno errx(1, "wait time is < 1ms"); 2548d2fbde5SJustin T. Gibbs break; 2556c359123SMaxim Konovalov case 'x': 2566c359123SMaxim Konovalov xflag++; 2576c359123SMaxim Konovalov break; 2586c359123SMaxim Konovalov case 'z': 2596c359123SMaxim Konovalov zflag++; 2606c359123SMaxim Konovalov break; 261dea673e9SRodney W. Grimes default: 262dea673e9SRodney W. Grimes usage(); 263dea673e9SRodney W. Grimes } 2648d2fbde5SJustin T. Gibbs } 2658d2fbde5SJustin T. Gibbs 266dea673e9SRodney W. Grimes argc -= optind; 267dea673e9SRodney W. Grimes argv += optind; 268dea673e9SRodney W. Grimes 2695dc445bfSKenneth D. Merry if (nlistf != NULL || memf != NULL) { 2705fc5ae5cSThomas Moestl kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 2715fc5ae5cSThomas Moestl 2725dc445bfSKenneth D. Merry if (kd == NULL) 2735fc5ae5cSThomas Moestl errx(1, "kvm_openfiles: %s", errbuf); 2745fc5ae5cSThomas Moestl 2755fc5ae5cSThomas Moestl if (kvm_nlist(kd, namelist) == -1) 2765fc5ae5cSThomas Moestl errx(1, "kvm_nlist: %s", kvm_geterr(kd)); 2775fc5ae5cSThomas Moestl } 278dea673e9SRodney W. Grimes 2798d2fbde5SJustin T. Gibbs /* 2808d2fbde5SJustin T. Gibbs * Make sure that the userland devstat version matches the kernel 2818d2fbde5SJustin T. Gibbs * devstat version. If not, exit and print a message informing 2828d2fbde5SJustin T. Gibbs * the user of his mistake. 2838d2fbde5SJustin T. Gibbs */ 2845fc5ae5cSThomas Moestl if (devstat_checkversion(kd) < 0) 2858d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 2868d2fbde5SJustin T. Gibbs 2878d2fbde5SJustin T. Gibbs /* 2885dc445bfSKenneth D. Merry * Make sure Tflag and/or Cflag are set if dflag == 0. If dflag is 2895dc445bfSKenneth D. Merry * greater than 0, they may be 0 or non-zero. 2905dc445bfSKenneth D. Merry */ 2916c359123SMaxim Konovalov if (dflag == 0 && xflag == 0) { 2925dc445bfSKenneth D. Merry Cflag = 1; 2935dc445bfSKenneth D. Merry Tflag = 1; 2945dc445bfSKenneth D. Merry } 2955dc445bfSKenneth D. Merry 296dd9bccc4SMaxim Konovalov /* find out how many devices we have */ 297dd9bccc4SMaxim Konovalov if ((num_devices = devstat_getnumdevs(kd)) < 0) 298dd9bccc4SMaxim Konovalov err(1, "can't get number of devices"); 299dd9bccc4SMaxim Konovalov 3005dc445bfSKenneth D. Merry /* 3018d2fbde5SJustin T. Gibbs * Figure out how many devices we should display. 3028d2fbde5SJustin T. Gibbs */ 3038d2fbde5SJustin T. Gibbs if (nflag == 0) { 304dd9bccc4SMaxim Konovalov if (xflag > 0) 305dd9bccc4SMaxim Konovalov maxshowdevs = num_devices; 306dd9bccc4SMaxim Konovalov else if (oflag > 0) { 3078d2fbde5SJustin T. Gibbs if ((dflag > 0) && (Cflag == 0) && (Tflag == 0)) 3088d2fbde5SJustin T. Gibbs maxshowdevs = 5; 3098d2fbde5SJustin T. Gibbs else if ((dflag > 0) && (Tflag > 0) && (Cflag == 0)) 3108d2fbde5SJustin T. Gibbs maxshowdevs = 5; 3118d2fbde5SJustin T. Gibbs else 3128d2fbde5SJustin T. Gibbs maxshowdevs = 4; 3138d2fbde5SJustin T. Gibbs } else { 3148d2fbde5SJustin T. Gibbs if ((dflag > 0) && (Cflag == 0)) 3158d2fbde5SJustin T. Gibbs maxshowdevs = 4; 3168d2fbde5SJustin T. Gibbs else 3178d2fbde5SJustin T. Gibbs maxshowdevs = 3; 3188d2fbde5SJustin T. Gibbs } 3198d2fbde5SJustin T. Gibbs } 3208d2fbde5SJustin T. Gibbs 3214f6e1368SXin LI cur.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)); 3225dc445bfSKenneth D. Merry if (cur.dinfo == NULL) 3234f6e1368SXin LI err(1, "calloc failed"); 3245dc445bfSKenneth D. Merry 3254f6e1368SXin LI last.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)); 3265dc445bfSKenneth D. Merry if (last.dinfo == NULL) 3274f6e1368SXin LI err(1, "calloc failed"); 3288d2fbde5SJustin T. Gibbs 3298d2fbde5SJustin T. Gibbs /* 3308d2fbde5SJustin T. Gibbs * Grab all the devices. We don't look to see if the list has 3318d2fbde5SJustin T. Gibbs * changed here, since it almost certainly has. We only look for 3328d2fbde5SJustin T. Gibbs * errors. 3338d2fbde5SJustin T. Gibbs */ 3345fc5ae5cSThomas Moestl if (devstat_getdevs(kd, &cur) == -1) 3358d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 3368d2fbde5SJustin T. Gibbs 3378d2fbde5SJustin T. Gibbs num_devices = cur.dinfo->numdevs; 3388d2fbde5SJustin T. Gibbs generation = cur.dinfo->generation; 3398d2fbde5SJustin T. Gibbs 3408d2fbde5SJustin T. Gibbs /* 3418d2fbde5SJustin T. Gibbs * If the user specified any devices on the command line, see if 3428d2fbde5SJustin T. Gibbs * they are in the list of devices we have now. 3438d2fbde5SJustin T. Gibbs */ 3445dc445bfSKenneth D. Merry specified_devices = (char **)malloc(sizeof(char *)); 3455dc445bfSKenneth D. Merry if (specified_devices == NULL) 3465dc445bfSKenneth D. Merry err(1, "malloc failed"); 3475dc445bfSKenneth D. Merry 3488d2fbde5SJustin T. Gibbs for (num_devices_specified = 0; *argv; ++argv) { 3498d2fbde5SJustin T. Gibbs if (isdigit(**argv)) 3508d2fbde5SJustin T. Gibbs break; 3518d2fbde5SJustin T. Gibbs num_devices_specified++; 3528d2fbde5SJustin T. Gibbs specified_devices = (char **)realloc(specified_devices, 3538d2fbde5SJustin T. Gibbs sizeof(char *) * 3548d2fbde5SJustin T. Gibbs num_devices_specified); 3555dc445bfSKenneth D. Merry if (specified_devices == NULL) 3565dc445bfSKenneth D. Merry err(1, "realloc failed"); 3575dc445bfSKenneth D. Merry 3588d2fbde5SJustin T. Gibbs specified_devices[num_devices_specified - 1] = *argv; 3598d2fbde5SJustin T. Gibbs 3608d2fbde5SJustin T. Gibbs } 3612fa4aaa0SMatthew Dillon if (nflag == 0 && maxshowdevs < num_devices_specified) 3622fa4aaa0SMatthew Dillon maxshowdevs = num_devices_specified; 3638d2fbde5SJustin T. Gibbs 3648d2fbde5SJustin T. Gibbs dev_select = NULL; 3658d2fbde5SJustin T. Gibbs 3668d2fbde5SJustin T. Gibbs if ((num_devices_specified == 0) && (num_matches == 0)) 3678d2fbde5SJustin T. Gibbs select_mode = DS_SELECT_ADD; 3688d2fbde5SJustin T. Gibbs else 3698d2fbde5SJustin T. Gibbs select_mode = DS_SELECT_ONLY; 3708d2fbde5SJustin T. Gibbs 3718d2fbde5SJustin T. Gibbs /* 3728d2fbde5SJustin T. Gibbs * At this point, selectdevs will almost surely indicate that the 3738d2fbde5SJustin T. Gibbs * device list has changed, so we don't look for return values of 0 3748d2fbde5SJustin T. Gibbs * or 1. If we get back -1, though, there is an error. 3758d2fbde5SJustin T. Gibbs */ 3765fc5ae5cSThomas Moestl if (devstat_selectdevs(&dev_select, &num_selected, 3775fc5ae5cSThomas Moestl &num_selections, &select_generation, generation, 3785fc5ae5cSThomas Moestl cur.dinfo->devices, num_devices, matches, 3795fc5ae5cSThomas Moestl num_matches, specified_devices, 3805fc5ae5cSThomas Moestl num_devices_specified, select_mode, maxshowdevs, 3815fc5ae5cSThomas Moestl hflag) == -1) 3828d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 3838d2fbde5SJustin T. Gibbs 3848d2fbde5SJustin T. Gibbs /* 3858d2fbde5SJustin T. Gibbs * Look for the traditional wait time and count arguments. 3868d2fbde5SJustin T. Gibbs */ 3878d2fbde5SJustin T. Gibbs if (*argv) { 3888b10473dSSean Bruno f = atof(*argv); 3898b10473dSSean Bruno waittime = f * 1000; 3908d2fbde5SJustin T. Gibbs 3918d2fbde5SJustin T. Gibbs /* Let the user know he goofed, but keep going anyway */ 3928d2fbde5SJustin T. Gibbs if (wflag != 0) 3938d2fbde5SJustin T. Gibbs warnx("discarding previous wait interval, using" 3948b10473dSSean Bruno " %g instead", waittime / 1000.0); 3958d2fbde5SJustin T. Gibbs wflag++; 3968d2fbde5SJustin T. Gibbs 3978d2fbde5SJustin T. Gibbs if (*++argv) { 3988d2fbde5SJustin T. Gibbs count = atoi(*argv); 3998d2fbde5SJustin T. Gibbs if (cflag != 0) 4008d2fbde5SJustin T. Gibbs warnx("discarding previous count, using %d" 4018d2fbde5SJustin T. Gibbs " instead", count); 4028d2fbde5SJustin T. Gibbs cflag++; 4038d2fbde5SJustin T. Gibbs } else 4048d2fbde5SJustin T. Gibbs count = -1; 4058d2fbde5SJustin T. Gibbs } 4068d2fbde5SJustin T. Gibbs 4078d2fbde5SJustin T. Gibbs /* 4088d2fbde5SJustin T. Gibbs * If the user specified a count, but not an interval, we default 4098d2fbde5SJustin T. Gibbs * to an interval of 1 second. 4108d2fbde5SJustin T. Gibbs */ 4118d2fbde5SJustin T. Gibbs if ((wflag == 0) && (cflag > 0)) 4128b10473dSSean Bruno waittime = 1 * 1000; 4138d2fbde5SJustin T. Gibbs 4148d2fbde5SJustin T. Gibbs /* 4158d2fbde5SJustin T. Gibbs * If the user specified a wait time, but not a count, we want to 4168d2fbde5SJustin T. Gibbs * go on ad infinitum. This can be redundant if the user uses the 4178d2fbde5SJustin T. Gibbs * traditional method of specifying the wait, since in that case we 4188d2fbde5SJustin T. Gibbs * already set count = -1 above. Oh well. 4198d2fbde5SJustin T. Gibbs */ 4208d2fbde5SJustin T. Gibbs if ((wflag > 0) && (cflag == 0)) 4218d2fbde5SJustin T. Gibbs count = -1; 4228d2fbde5SJustin T. Gibbs 4239e5fbab2SJohn Baldwin bzero(cur.cp_time, sizeof(cur.cp_time)); 4245dc445bfSKenneth D. Merry cur.tk_nout = 0; 4255dc445bfSKenneth D. Merry cur.tk_nin = 0; 4265dc445bfSKenneth D. Merry 4275dc445bfSKenneth D. Merry /* 4287194d335SPoul-Henning Kamp * Set the snap time to the system boot time (ie: zero), so the 4297194d335SPoul-Henning Kamp * stats are calculated since system boot. 4305dc445bfSKenneth D. Merry */ 4317194d335SPoul-Henning Kamp cur.snap_time = 0; 4325dc445bfSKenneth D. Merry 433dea673e9SRodney W. Grimes /* 4348d2fbde5SJustin T. Gibbs * If the user stops the program (control-Z) and then resumes it, 4358d2fbde5SJustin T. Gibbs * print out the header again. 436dea673e9SRodney W. Grimes */ 437775b0074SGuido van Rooij (void)signal(SIGCONT, needhdr); 438dea673e9SRodney W. Grimes 43953fbcd3aSGiorgos Keramidas /* 44053fbcd3aSGiorgos Keramidas * If our standard output is a tty, then install a SIGWINCH handler 44153fbcd3aSGiorgos Keramidas * and set wresized so that our first iteration through the main 44253fbcd3aSGiorgos Keramidas * iostat loop will peek at the terminal's current rows to find out 44353fbcd3aSGiorgos Keramidas * how many lines can fit in a screenful of output. 44453fbcd3aSGiorgos Keramidas */ 44553fbcd3aSGiorgos Keramidas if (isatty(fileno(stdout)) != 0) { 44653fbcd3aSGiorgos Keramidas wresized = 1; 44753fbcd3aSGiorgos Keramidas (void)signal(SIGWINCH, needresize); 44853fbcd3aSGiorgos Keramidas } else { 44953fbcd3aSGiorgos Keramidas wresized = 0; 45053fbcd3aSGiorgos Keramidas wrows = IOSTAT_DEFAULT_ROWS; 45153fbcd3aSGiorgos Keramidas } 45253fbcd3aSGiorgos Keramidas 453da61e79cSAlan Somers /* 454da61e79cSAlan Somers * Register a SIGINT handler so that we can print out final statistics 455da61e79cSAlan Somers * when we get that signal 456da61e79cSAlan Somers */ 457da61e79cSAlan Somers (void)signal(SIGINT, needreturn); 458da61e79cSAlan Somers 459da61e79cSAlan Somers /* 460da61e79cSAlan Somers * Register a SIGALRM handler to implement sleeps if the user uses the 461da61e79cSAlan Somers * -c or -w options 462da61e79cSAlan Somers */ 463da61e79cSAlan Somers (void)signal(SIGALRM, alarm_clock); 464da61e79cSAlan Somers alarmspec.it_interval.tv_sec = waittime / 1000; 465da61e79cSAlan Somers alarmspec.it_interval.tv_usec = 1000 * (waittime % 1000); 466da61e79cSAlan Somers alarmspec.it_value.tv_sec = waittime / 1000; 467da61e79cSAlan Somers alarmspec.it_value.tv_usec = 1000 * (waittime % 1000); 468da61e79cSAlan Somers setitimer(ITIMER_REAL, &alarmspec, NULL); 469da61e79cSAlan Somers 4708d2fbde5SJustin T. Gibbs for (headercount = 1;;) { 4718d2fbde5SJustin T. Gibbs struct devinfo *tmp_dinfo; 4728d2fbde5SJustin T. Gibbs long tmp; 4735dc445bfSKenneth D. Merry long double etime; 474da61e79cSAlan Somers sigset_t sigmask, oldsigmask; 4755dc445bfSKenneth D. Merry 4765dc445bfSKenneth D. Merry if (Tflag > 0) { 4778cb3704aSSergey Kandaurov if ((readvar(kd, "kern.tty_nin", X_TTY_NIN, &cur.tk_nin, 4785dc445bfSKenneth D. Merry sizeof(cur.tk_nin)) != 0) 4798cb3704aSSergey Kandaurov || (readvar(kd, "kern.tty_nout", X_TTY_NOUT, 4805dc445bfSKenneth D. Merry &cur.tk_nout, sizeof(cur.tk_nout))!= 0)) { 4815dc445bfSKenneth D. Merry Tflag = 0; 4825dc445bfSKenneth D. Merry warnx("disabling TTY statistics"); 4835dc445bfSKenneth D. Merry } 4845dc445bfSKenneth D. Merry } 4855dc445bfSKenneth D. Merry 4865dc445bfSKenneth D. Merry if (Cflag > 0) { 48732c9e3bdSJohn Baldwin if (kd == NULL) { 48832c9e3bdSJohn Baldwin if (readvar(kd, "kern.cp_time", 0, 48932c9e3bdSJohn Baldwin &cur.cp_time, sizeof(cur.cp_time)) != 0) 4905dc445bfSKenneth D. Merry Cflag = 0; 49132c9e3bdSJohn Baldwin } else { 49232c9e3bdSJohn Baldwin if (kvm_getcptime(kd, cur.cp_time) < 0) { 49332c9e3bdSJohn Baldwin warnx("kvm_getcptime: %s", 49432c9e3bdSJohn Baldwin kvm_geterr(kd)); 49532c9e3bdSJohn Baldwin Cflag = 0; 4965dc445bfSKenneth D. Merry } 4975dc445bfSKenneth D. Merry } 49832c9e3bdSJohn Baldwin if (Cflag == 0) 49932c9e3bdSJohn Baldwin warnx("disabling CPU time statistics"); 50032c9e3bdSJohn Baldwin } 5018d2fbde5SJustin T. Gibbs 5028d2fbde5SJustin T. Gibbs if (!--headercount) { 503775b0074SGuido van Rooij phdr(); 50453fbcd3aSGiorgos Keramidas if (wresized != 0) 50553fbcd3aSGiorgos Keramidas doresize(); 50653fbcd3aSGiorgos Keramidas headercount = wrows; 507dea673e9SRodney W. Grimes } 5088d2fbde5SJustin T. Gibbs 5098d2fbde5SJustin T. Gibbs tmp_dinfo = last.dinfo; 5108d2fbde5SJustin T. Gibbs last.dinfo = cur.dinfo; 5118d2fbde5SJustin T. Gibbs cur.dinfo = tmp_dinfo; 5128d2fbde5SJustin T. Gibbs 5137194d335SPoul-Henning Kamp last.snap_time = cur.snap_time; 5148d2fbde5SJustin T. Gibbs 5158d2fbde5SJustin T. Gibbs /* 5168d2fbde5SJustin T. Gibbs * Here what we want to do is refresh our device stats. 5175fc5ae5cSThomas Moestl * devstat_getdevs() returns 1 when the device list has changed. 5188d2fbde5SJustin T. Gibbs * If the device list has changed, we want to go through 5198d2fbde5SJustin T. Gibbs * the selection process again, in case a device that we 5208d2fbde5SJustin T. Gibbs * were previously displaying has gone away. 5218d2fbde5SJustin T. Gibbs */ 5225fc5ae5cSThomas Moestl switch (devstat_getdevs(kd, &cur)) { 5238d2fbde5SJustin T. Gibbs case -1: 5248d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 5258d2fbde5SJustin T. Gibbs break; 5268d2fbde5SJustin T. Gibbs case 1: { 5278d2fbde5SJustin T. Gibbs int retval; 5288d2fbde5SJustin T. Gibbs 5298d2fbde5SJustin T. Gibbs num_devices = cur.dinfo->numdevs; 5308d2fbde5SJustin T. Gibbs generation = cur.dinfo->generation; 5315fc5ae5cSThomas Moestl retval = devstat_selectdevs(&dev_select, &num_selected, 5325fc5ae5cSThomas Moestl &num_selections, 5335fc5ae5cSThomas Moestl &select_generation, 5345fc5ae5cSThomas Moestl generation, 5355fc5ae5cSThomas Moestl cur.dinfo->devices, 5365fc5ae5cSThomas Moestl num_devices, matches, 5375fc5ae5cSThomas Moestl num_matches, 5388d2fbde5SJustin T. Gibbs specified_devices, 5398d2fbde5SJustin T. Gibbs num_devices_specified, 5405fc5ae5cSThomas Moestl select_mode, maxshowdevs, 5415fc5ae5cSThomas Moestl hflag); 5428d2fbde5SJustin T. Gibbs switch(retval) { 5438d2fbde5SJustin T. Gibbs case -1: 5448d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 5458d2fbde5SJustin T. Gibbs break; 5468d2fbde5SJustin T. Gibbs case 1: 547775b0074SGuido van Rooij phdr(); 54853fbcd3aSGiorgos Keramidas if (wresized != 0) 54953fbcd3aSGiorgos Keramidas doresize(); 55053fbcd3aSGiorgos Keramidas headercount = wrows; 5518d2fbde5SJustin T. Gibbs break; 5528d2fbde5SJustin T. Gibbs default: 5538d2fbde5SJustin T. Gibbs break; 554dea673e9SRodney W. Grimes } 5558d2fbde5SJustin T. Gibbs break; 5568d2fbde5SJustin T. Gibbs } 5578d2fbde5SJustin T. Gibbs default: 5588d2fbde5SJustin T. Gibbs break; 5598d2fbde5SJustin T. Gibbs } 5608d2fbde5SJustin T. Gibbs 5618d2fbde5SJustin T. Gibbs /* 5628d2fbde5SJustin T. Gibbs * We only want to re-select devices if we're in 'top' 5638d2fbde5SJustin T. Gibbs * mode. This is the only mode where the devices selected 5648d2fbde5SJustin T. Gibbs * could actually change. 5658d2fbde5SJustin T. Gibbs */ 5668d2fbde5SJustin T. Gibbs if (hflag > 0) { 5678d2fbde5SJustin T. Gibbs int retval; 5685fc5ae5cSThomas Moestl retval = devstat_selectdevs(&dev_select, &num_selected, 5695fc5ae5cSThomas Moestl &num_selections, 5705fc5ae5cSThomas Moestl &select_generation, 5715fc5ae5cSThomas Moestl generation, 5725fc5ae5cSThomas Moestl cur.dinfo->devices, 5735fc5ae5cSThomas Moestl num_devices, matches, 5745fc5ae5cSThomas Moestl num_matches, 5758d2fbde5SJustin T. Gibbs specified_devices, 5768d2fbde5SJustin T. Gibbs num_devices_specified, 5775fc5ae5cSThomas Moestl select_mode, maxshowdevs, 5785fc5ae5cSThomas Moestl hflag); 5798d2fbde5SJustin T. Gibbs switch(retval) { 5808d2fbde5SJustin T. Gibbs case -1: 5818d2fbde5SJustin T. Gibbs errx(1,"%s", devstat_errbuf); 5828d2fbde5SJustin T. Gibbs break; 5838d2fbde5SJustin T. Gibbs case 1: 584775b0074SGuido van Rooij phdr(); 58553fbcd3aSGiorgos Keramidas if (wresized != 0) 58653fbcd3aSGiorgos Keramidas doresize(); 58753fbcd3aSGiorgos Keramidas headercount = wrows; 5888d2fbde5SJustin T. Gibbs break; 5898d2fbde5SJustin T. Gibbs default: 5908d2fbde5SJustin T. Gibbs break; 5918d2fbde5SJustin T. Gibbs } 5928d2fbde5SJustin T. Gibbs } 5938d2fbde5SJustin T. Gibbs 5945dc445bfSKenneth D. Merry if (Tflag > 0) { 595dea673e9SRodney W. Grimes tmp = cur.tk_nin; 596dea673e9SRodney W. Grimes cur.tk_nin -= last.tk_nin; 597dea673e9SRodney W. Grimes last.tk_nin = tmp; 598dea673e9SRodney W. Grimes tmp = cur.tk_nout; 599dea673e9SRodney W. Grimes cur.tk_nout -= last.tk_nout; 600dea673e9SRodney W. Grimes last.tk_nout = tmp; 601dea673e9SRodney W. Grimes } 6025dc445bfSKenneth D. Merry 6037194d335SPoul-Henning Kamp etime = cur.snap_time - last.snap_time; 6045dc445bfSKenneth D. Merry 605dea673e9SRodney W. Grimes if (etime == 0.0) 606dea673e9SRodney W. Grimes etime = 1.0; 6075dc445bfSKenneth D. Merry 6085dc445bfSKenneth D. Merry for (i = 0; i < CPUSTATES; i++) { 6095dc445bfSKenneth D. Merry tmp = cur.cp_time[i]; 6105dc445bfSKenneth D. Merry cur.cp_time[i] -= last.cp_time[i]; 6115dc445bfSKenneth D. Merry last.cp_time[i] = tmp; 6125dc445bfSKenneth D. Merry } 6135dc445bfSKenneth D. Merry 6146c359123SMaxim Konovalov if (xflag == 0 && Tflag > 0) 6155dc445bfSKenneth D. Merry printf("%4.0Lf %5.0Lf", cur.tk_nin / etime, 6168d2fbde5SJustin T. Gibbs cur.tk_nout / etime); 6175dc445bfSKenneth D. Merry 6185fc5ae5cSThomas Moestl devstats(hflag, etime, havelast); 6195dc445bfSKenneth D. Merry 6206c359123SMaxim Konovalov if (xflag == 0) { 6215dc445bfSKenneth D. Merry if (Cflag > 0) 622dea673e9SRodney W. Grimes cpustats(); 6235dc445bfSKenneth D. Merry 6248d2fbde5SJustin T. Gibbs printf("\n"); 6256c359123SMaxim Konovalov } 6268d2fbde5SJustin T. Gibbs fflush(stdout); 627dea673e9SRodney W. Grimes 628da61e79cSAlan Somers if ((count >= 0 && --count <= 0) || return_requested) 629dea673e9SRodney W. Grimes break; 6308d2fbde5SJustin T. Gibbs 631da61e79cSAlan Somers /* 632da61e79cSAlan Somers * Use sigsuspend to safely sleep until either signal is 633da61e79cSAlan Somers * received 634da61e79cSAlan Somers */ 635da61e79cSAlan Somers alarm_rang = 0; 636da61e79cSAlan Somers sigemptyset(&sigmask); 637da61e79cSAlan Somers sigaddset(&sigmask, SIGINT); 638da61e79cSAlan Somers sigaddset(&sigmask, SIGALRM); 639da61e79cSAlan Somers sigprocmask(SIG_BLOCK, &sigmask, &oldsigmask); 640da61e79cSAlan Somers while (! (alarm_rang || return_requested) ) { 641da61e79cSAlan Somers sigsuspend(&oldsigmask); 642da61e79cSAlan Somers } 643da61e79cSAlan Somers sigprocmask(SIG_UNBLOCK, &sigmask, NULL); 644da61e79cSAlan Somers 6455fc5ae5cSThomas Moestl havelast = 1; 646dea673e9SRodney W. Grimes } 6478d2fbde5SJustin T. Gibbs 648dea673e9SRodney W. Grimes exit(0); 649dea673e9SRodney W. Grimes } 650dea673e9SRodney W. Grimes 651775b0074SGuido van Rooij /* 652775b0074SGuido van Rooij * Force a header to be prepended to the next output. 653775b0074SGuido van Rooij */ 654775b0074SGuido van Rooij void 655a59c2129SAlan Somers needhdr(int signo __unused) 656dea673e9SRodney W. Grimes { 657e65cded7SKris Kennaway 658775b0074SGuido van Rooij headercount = 1; 659e65cded7SKris Kennaway } 660e65cded7SKris Kennaway 66153fbcd3aSGiorgos Keramidas /* 66253fbcd3aSGiorgos Keramidas * When the terminal is resized, force an update of the maximum number of rows 66353fbcd3aSGiorgos Keramidas * printed between each header repetition. Then force a new header to be 66453fbcd3aSGiorgos Keramidas * prepended to the next output. 66553fbcd3aSGiorgos Keramidas */ 66653fbcd3aSGiorgos Keramidas void 667a59c2129SAlan Somers needresize(int signo __unused) 66853fbcd3aSGiorgos Keramidas { 66953fbcd3aSGiorgos Keramidas 67053fbcd3aSGiorgos Keramidas wresized = 1; 67153fbcd3aSGiorgos Keramidas headercount = 1; 67253fbcd3aSGiorgos Keramidas } 67353fbcd3aSGiorgos Keramidas 67453fbcd3aSGiorgos Keramidas /* 675da61e79cSAlan Somers * Record the alarm so the main loop can break its sleep 676da61e79cSAlan Somers */ 677da61e79cSAlan Somers void 678a59c2129SAlan Somers alarm_clock(int signo __unused) 679da61e79cSAlan Somers { 680da61e79cSAlan Somers alarm_rang = 1; 681da61e79cSAlan Somers } 682da61e79cSAlan Somers 683da61e79cSAlan Somers /* 684da61e79cSAlan Somers * Request that the main loop exit soon 685da61e79cSAlan Somers */ 686da61e79cSAlan Somers void 687a59c2129SAlan Somers needreturn(int signo __unused) 688da61e79cSAlan Somers { 689da61e79cSAlan Somers return_requested = 1; 690da61e79cSAlan Somers } 691da61e79cSAlan Somers 692da61e79cSAlan Somers /* 69353fbcd3aSGiorgos Keramidas * Update the global `wrows' count of terminal rows. 69453fbcd3aSGiorgos Keramidas */ 69553fbcd3aSGiorgos Keramidas void 69653fbcd3aSGiorgos Keramidas doresize(void) 69753fbcd3aSGiorgos Keramidas { 69853fbcd3aSGiorgos Keramidas int status; 69953fbcd3aSGiorgos Keramidas struct winsize w; 70053fbcd3aSGiorgos Keramidas 70153fbcd3aSGiorgos Keramidas for (;;) { 70253fbcd3aSGiorgos Keramidas status = ioctl(fileno(stdout), TIOCGWINSZ, &w); 70353fbcd3aSGiorgos Keramidas if (status == -1 && errno == EINTR) 70453fbcd3aSGiorgos Keramidas continue; 70553fbcd3aSGiorgos Keramidas else if (status == -1) 70653fbcd3aSGiorgos Keramidas err(1, "ioctl"); 70753fbcd3aSGiorgos Keramidas if (w.ws_row > 3) 70853fbcd3aSGiorgos Keramidas wrows = w.ws_row - 3; 70953fbcd3aSGiorgos Keramidas else 71053fbcd3aSGiorgos Keramidas wrows = IOSTAT_DEFAULT_ROWS; 71153fbcd3aSGiorgos Keramidas break; 71253fbcd3aSGiorgos Keramidas } 71353fbcd3aSGiorgos Keramidas 71453fbcd3aSGiorgos Keramidas /* 71553fbcd3aSGiorgos Keramidas * Inhibit doresize() calls until we are rescheduled by SIGWINCH. 71653fbcd3aSGiorgos Keramidas */ 71753fbcd3aSGiorgos Keramidas wresized = 0; 71853fbcd3aSGiorgos Keramidas } 71953fbcd3aSGiorgos Keramidas 720e65cded7SKris Kennaway static void 721775b0074SGuido van Rooij phdr(void) 722e65cded7SKris Kennaway { 72347e065b4SMaxim Konovalov int i, printed; 724ab8ac08eSAdrian Chadd char devbuf[256]; 725dea673e9SRodney W. Grimes 7266c359123SMaxim Konovalov /* 7276c359123SMaxim Konovalov * If xflag is set, we need a per-loop header, not a page header, so 7286c359123SMaxim Konovalov * just return. We'll print the header in devstats(). 7296c359123SMaxim Konovalov */ 7306c359123SMaxim Konovalov if (xflag > 0) 7316c359123SMaxim Konovalov return; 7326c359123SMaxim Konovalov 7335dc445bfSKenneth D. Merry if (Tflag > 0) 734dea673e9SRodney W. Grimes (void)printf(" tty"); 7358d2fbde5SJustin T. Gibbs for (i = 0, printed=0;(i < num_devices) && (printed < maxshowdevs);i++){ 7368d2fbde5SJustin T. Gibbs int di; 7378d2fbde5SJustin T. Gibbs if ((dev_select[i].selected != 0) 7388d2fbde5SJustin T. Gibbs && (dev_select[i].selected <= maxshowdevs)) { 7398d2fbde5SJustin T. Gibbs di = dev_select[i].position; 740ab8ac08eSAdrian Chadd snprintf(devbuf, sizeof(devbuf), "%s%d", 741ab8ac08eSAdrian Chadd cur.dinfo->devices[di].device_name, 742ab8ac08eSAdrian Chadd cur.dinfo->devices[di].unit_number); 7438d2fbde5SJustin T. Gibbs if (oflag > 0) 744ab8ac08eSAdrian Chadd (void)printf("%13.6s ", devbuf); 7458d2fbde5SJustin T. Gibbs else 746ab8ac08eSAdrian Chadd printf("%16.6s ", devbuf); 7478d2fbde5SJustin T. Gibbs printed++; 7488d2fbde5SJustin T. Gibbs } 7498d2fbde5SJustin T. Gibbs } 7505dc445bfSKenneth D. Merry if (Cflag > 0) 7518d2fbde5SJustin T. Gibbs (void)printf(" cpu\n"); 7528d2fbde5SJustin T. Gibbs else 7538d2fbde5SJustin T. Gibbs (void)printf("\n"); 7548d2fbde5SJustin T. Gibbs 7555dc445bfSKenneth D. Merry if (Tflag > 0) 7568d2fbde5SJustin T. Gibbs (void)printf(" tin tout"); 7578d2fbde5SJustin T. Gibbs 7588d2fbde5SJustin T. Gibbs for (i=0, printed = 0;(i < num_devices) && (printed < maxshowdevs);i++){ 7598d2fbde5SJustin T. Gibbs if ((dev_select[i].selected != 0) 7608d2fbde5SJustin T. Gibbs && (dev_select[i].selected <= maxshowdevs)) { 7612fa4aaa0SMatthew Dillon if (oflag > 0) { 7628d2fbde5SJustin T. Gibbs if (Iflag == 0) 763dea673e9SRodney W. Grimes (void)printf(" sps tps msps "); 7648d2fbde5SJustin T. Gibbs else 7658d2fbde5SJustin T. Gibbs (void)printf(" blk xfr msps "); 7662fa4aaa0SMatthew Dillon } else { 7678d2fbde5SJustin T. Gibbs if (Iflag == 0) 7688d2fbde5SJustin T. Gibbs printf("KB/t tps MB/s "); 7698d2fbde5SJustin T. Gibbs else 7708d2fbde5SJustin T. Gibbs printf("KB/t xfrs MB "); 7712fa4aaa0SMatthew Dillon } 7728d2fbde5SJustin T. Gibbs printed++; 7738d2fbde5SJustin T. Gibbs } 7748d2fbde5SJustin T. Gibbs } 7755dc445bfSKenneth D. Merry if (Cflag > 0) 776936d754aSAndrey A. Chernov (void)printf(" us ni sy in id\n"); 7778d2fbde5SJustin T. Gibbs else 7788d2fbde5SJustin T. Gibbs printf("\n"); 779775b0074SGuido van Rooij 780dea673e9SRodney W. Grimes } 781dea673e9SRodney W. Grimes 7828d2fbde5SJustin T. Gibbs static void 7835dc445bfSKenneth D. Merry devstats(int perf_select, long double etime, int havelast) 784dea673e9SRodney W. Grimes { 78547e065b4SMaxim Konovalov int dn; 786abf607edSWill Andrews long double transfers_per_second, transfers_per_second_read; 787abf607edSWill Andrews long double transfers_per_second_write; 788abf607edSWill Andrews long double kb_per_transfer, mb_per_second, mb_per_second_read; 789abf607edSWill Andrews long double mb_per_second_write; 7908d2fbde5SJustin T. Gibbs u_int64_t total_bytes, total_transfers, total_blocks; 79130ff1266SMaxim Konovalov u_int64_t total_bytes_read, total_transfers_read; 79230ff1266SMaxim Konovalov u_int64_t total_bytes_write, total_transfers_write; 7933cfa2135SMikolaj Golub long double busy_pct, busy_time; 7946c359123SMaxim Konovalov u_int64_t queue_len; 795abf607edSWill Andrews long double total_mb, blocks_per_second, total_duration; 796abf607edSWill Andrews long double ms_per_other, ms_per_read, ms_per_write, ms_per_transaction; 7976c359123SMaxim Konovalov int firstline = 1; 79801368cfaSAlan Somers char *devicename; 7996c359123SMaxim Konovalov 8006c359123SMaxim Konovalov if (xflag > 0) { 8010484aa6dSAllan Jude if (Cflag > 0) { 8020484aa6dSAllan Jude printf(" cpu\n"); 8030484aa6dSAllan Jude printf(" us ni sy in id\n"); 8040484aa6dSAllan Jude cpustats(); 8050484aa6dSAllan Jude printf("\n"); 8060484aa6dSAllan Jude } 8076c359123SMaxim Konovalov printf(" extended device statistics "); 8086c359123SMaxim Konovalov if (Tflag > 0) 8096c359123SMaxim Konovalov printf(" tty "); 8106c359123SMaxim Konovalov printf("\n"); 8113cfa2135SMikolaj Golub if (Iflag == 0) { 812abf607edSWill Andrews printf("device r/s w/s kr/s kw/s " 813abf607edSWill Andrews " ms/r ms/w ms/o ms/t qlen %%b "); 8143cfa2135SMikolaj Golub } else { 8153cfa2135SMikolaj Golub printf("device r/i w/i kr/i" 8163cfa2135SMikolaj Golub " kw/i qlen tsvc_t/i sb/i "); 8173cfa2135SMikolaj Golub } 8186c359123SMaxim Konovalov if (Tflag > 0) 8196c359123SMaxim Konovalov printf("tin tout "); 8206c359123SMaxim Konovalov printf("\n"); 8216c359123SMaxim Konovalov } 822dea673e9SRodney W. Grimes 8238d2fbde5SJustin T. Gibbs for (dn = 0; dn < num_devices; dn++) { 8248d2fbde5SJustin T. Gibbs int di; 8258d2fbde5SJustin T. Gibbs 8268d2fbde5SJustin T. Gibbs if (((perf_select == 0) && (dev_select[dn].selected == 0)) 8278d2fbde5SJustin T. Gibbs || (dev_select[dn].selected > maxshowdevs)) 828dea673e9SRodney W. Grimes continue; 829dea673e9SRodney W. Grimes 8308d2fbde5SJustin T. Gibbs di = dev_select[dn].position; 831dea673e9SRodney W. Grimes 8325fc5ae5cSThomas Moestl if (devstat_compute_statistics(&cur.dinfo->devices[di], 8335dc445bfSKenneth D. Merry havelast ? &last.dinfo->devices[di] : NULL, etime, 8345fc5ae5cSThomas Moestl DSM_TOTAL_BYTES, &total_bytes, 83530ff1266SMaxim Konovalov DSM_TOTAL_BYTES_READ, &total_bytes_read, 83630ff1266SMaxim Konovalov DSM_TOTAL_BYTES_WRITE, &total_bytes_write, 8375fc5ae5cSThomas Moestl DSM_TOTAL_TRANSFERS, &total_transfers, 83830ff1266SMaxim Konovalov DSM_TOTAL_TRANSFERS_READ, &total_transfers_read, 83930ff1266SMaxim Konovalov DSM_TOTAL_TRANSFERS_WRITE, &total_transfers_write, 8405fc5ae5cSThomas Moestl DSM_TOTAL_BLOCKS, &total_blocks, 8415fc5ae5cSThomas Moestl DSM_KB_PER_TRANSFER, &kb_per_transfer, 8425fc5ae5cSThomas Moestl DSM_TRANSFERS_PER_SECOND, &transfers_per_second, 8436c359123SMaxim Konovalov DSM_TRANSFERS_PER_SECOND_READ, &transfers_per_second_read, 8446c359123SMaxim Konovalov DSM_TRANSFERS_PER_SECOND_WRITE, &transfers_per_second_write, 8455fc5ae5cSThomas Moestl DSM_MB_PER_SECOND, &mb_per_second, 8466c359123SMaxim Konovalov DSM_MB_PER_SECOND_READ, &mb_per_second_read, 8476c359123SMaxim Konovalov DSM_MB_PER_SECOND_WRITE, &mb_per_second_write, 8485fc5ae5cSThomas Moestl DSM_BLOCKS_PER_SECOND, &blocks_per_second, 8495fc5ae5cSThomas Moestl DSM_MS_PER_TRANSACTION, &ms_per_transaction, 850abf607edSWill Andrews DSM_MS_PER_TRANSACTION_READ, &ms_per_read, 851abf607edSWill Andrews DSM_MS_PER_TRANSACTION_WRITE, &ms_per_write, 852abf607edSWill Andrews DSM_MS_PER_TRANSACTION_OTHER, &ms_per_other, 8536c359123SMaxim Konovalov DSM_BUSY_PCT, &busy_pct, 8546c359123SMaxim Konovalov DSM_QUEUE_LENGTH, &queue_len, 8553cfa2135SMikolaj Golub DSM_TOTAL_DURATION, &total_duration, 8563cfa2135SMikolaj Golub DSM_TOTAL_BUSY_TIME, &busy_time, 8575fc5ae5cSThomas Moestl DSM_NONE) != 0) 8588d2fbde5SJustin T. Gibbs errx(1, "%s", devstat_errbuf); 8598d2fbde5SJustin T. Gibbs 8608d2fbde5SJustin T. Gibbs if (perf_select != 0) { 8618d2fbde5SJustin T. Gibbs dev_select[dn].bytes = total_bytes; 8628d2fbde5SJustin T. Gibbs if ((dev_select[dn].selected == 0) 8638d2fbde5SJustin T. Gibbs || (dev_select[dn].selected > maxshowdevs)) 8648d2fbde5SJustin T. Gibbs continue; 8658d2fbde5SJustin T. Gibbs } 8668d2fbde5SJustin T. Gibbs 8676c359123SMaxim Konovalov if (Kflag > 0 || xflag > 0) { 8682fa4aaa0SMatthew Dillon int block_size = cur.dinfo->devices[di].block_size; 869e4d7fe02SKenneth D. Merry total_blocks = total_blocks * (block_size ? 870e4d7fe02SKenneth D. Merry block_size : 512) / 1024; 8712fa4aaa0SMatthew Dillon } 8722fa4aaa0SMatthew Dillon 8736c359123SMaxim Konovalov if (xflag > 0) { 87401368cfaSAlan Somers if (asprintf(&devicename, "%s%d", 8756c359123SMaxim Konovalov cur.dinfo->devices[di].device_name, 876e08b1089SMaxim Konovalov cur.dinfo->devices[di].unit_number) == -1) 877e08b1089SMaxim Konovalov err(1, "asprintf"); 8786c359123SMaxim Konovalov /* 8796c359123SMaxim Konovalov * If zflag is set, skip any devices with zero I/O. 8806c359123SMaxim Konovalov */ 8816c359123SMaxim Konovalov if (zflag == 0 || transfers_per_second_read > 0.05 || 8826c359123SMaxim Konovalov transfers_per_second_write > 0.05 || 8836c359123SMaxim Konovalov mb_per_second_read > ((long double).0005)/1024 || 8846c359123SMaxim Konovalov mb_per_second_write > ((long double).0005)/1024 || 8856c359123SMaxim Konovalov busy_pct > 0.5) { 88630ff1266SMaxim Konovalov if (Iflag == 0) 88761631b24SAlan Somers printf("%-8.8s %7.0Lf %7.0Lf %8.1Lf " 88861631b24SAlan Somers "%8.1Lf %5.0Lf %5.0Lf %5.0Lf %5.0Lf" 889abf607edSWill Andrews " %4" PRIu64 " %3.0Lf ", 89001368cfaSAlan Somers devicename, 89161631b24SAlan Somers transfers_per_second_read, 89261631b24SAlan Somers transfers_per_second_write, 8936c359123SMaxim Konovalov mb_per_second_read * 1024, 894fbe4fc2eSMaxim Konovalov mb_per_second_write * 1024, 89561631b24SAlan Somers ms_per_read, ms_per_write, 89661631b24SAlan Somers ms_per_other, 89761631b24SAlan Somers ms_per_transaction, 898abf607edSWill Andrews queue_len, busy_pct); 89930ff1266SMaxim Konovalov else 9003cfa2135SMikolaj Golub printf("%-8.8s %11.1Lf %11.1Lf " 9013cfa2135SMikolaj Golub "%12.1Lf %12.1Lf %4" PRIu64 9023cfa2135SMikolaj Golub " %10.1Lf %9.1Lf ", 90301368cfaSAlan Somers devicename, 904fbe4fc2eSMaxim Konovalov (long double)total_transfers_read, 90530ff1266SMaxim Konovalov (long double)total_transfers_write, 906fbe4fc2eSMaxim Konovalov (long double) 907fbe4fc2eSMaxim Konovalov total_bytes_read / 1024, 908fbe4fc2eSMaxim Konovalov (long double) 909fbe4fc2eSMaxim Konovalov total_bytes_write / 1024, 910fbe4fc2eSMaxim Konovalov queue_len, 9113cfa2135SMikolaj Golub total_duration, busy_time); 9126c359123SMaxim Konovalov if (firstline) { 9136c359123SMaxim Konovalov /* 9146c359123SMaxim Konovalov * If this is the first device 9156c359123SMaxim Konovalov * we're printing, also print 9166c359123SMaxim Konovalov * CPU or TTY stats if requested. 9176c359123SMaxim Konovalov */ 9186c359123SMaxim Konovalov firstline = 0; 9196c359123SMaxim Konovalov if (Tflag > 0) 9206c359123SMaxim Konovalov printf("%4.0Lf%5.0Lf", 9216c359123SMaxim Konovalov cur.tk_nin / etime, 9226c359123SMaxim Konovalov cur.tk_nout / etime); 9236c359123SMaxim Konovalov } 9246c359123SMaxim Konovalov printf("\n"); 9256c359123SMaxim Konovalov } 92601368cfaSAlan Somers free(devicename); 9276c359123SMaxim Konovalov } else if (oflag > 0) { 928125de826SEdward Tomasz Napierala int msdig = (ms_per_transaction < 99.94) ? 1 : 0; 9298d2fbde5SJustin T. Gibbs 9308d2fbde5SJustin T. Gibbs if (Iflag == 0) 9312fa4aaa0SMatthew Dillon printf("%4.0Lf%4.0Lf%5.*Lf ", 9328d2fbde5SJustin T. Gibbs blocks_per_second, 9338d2fbde5SJustin T. Gibbs transfers_per_second, 9342fa4aaa0SMatthew Dillon msdig, 9358d2fbde5SJustin T. Gibbs ms_per_transaction); 936dea673e9SRodney W. Grimes else 937*105c7c4bSAlexander Motin printf("%4" PRIu64 "%4" PRIu64 "%5.*Lf ", 9388d2fbde5SJustin T. Gibbs total_blocks, 9398d2fbde5SJustin T. Gibbs total_transfers, 9402fa4aaa0SMatthew Dillon msdig, 9418d2fbde5SJustin T. Gibbs ms_per_transaction); 9428d2fbde5SJustin T. Gibbs } else { 9438d2fbde5SJustin T. Gibbs if (Iflag == 0) 944*105c7c4bSAlexander Motin printf("%4.*Lf %5.0Lf %5.*Lf ", 94583743daeSEdward Tomasz Napierala kb_per_transfer >= 100 ? 0 : 1, 9468d2fbde5SJustin T. Gibbs kb_per_transfer, 9478d2fbde5SJustin T. Gibbs transfers_per_second, 948*105c7c4bSAlexander Motin mb_per_second >= 1000 ? 0 : 949*105c7c4bSAlexander Motin (total_mb >= 100 ? 1 : 2), 9508d2fbde5SJustin T. Gibbs mb_per_second); 9518d2fbde5SJustin T. Gibbs else { 9528d2fbde5SJustin T. Gibbs total_mb = total_bytes; 9538d2fbde5SJustin T. Gibbs total_mb /= 1024 * 1024; 9548d2fbde5SJustin T. Gibbs 955*105c7c4bSAlexander Motin printf("%4.*Lf %5" PRIu64 " %5.*Lf ", 956*105c7c4bSAlexander Motin kb_per_transfer >= 100 ? 0 : 1, 9578d2fbde5SJustin T. Gibbs kb_per_transfer, 9588d2fbde5SJustin T. Gibbs total_transfers, 959*105c7c4bSAlexander Motin total_mb >= 1000 ? 0 : 960*105c7c4bSAlexander Motin (total_mb >= 100 ? 1 : 2), 9618d2fbde5SJustin T. Gibbs total_mb); 9628d2fbde5SJustin T. Gibbs } 9638d2fbde5SJustin T. Gibbs } 964dea673e9SRodney W. Grimes } 9656c359123SMaxim Konovalov if (xflag > 0 && zflag > 0 && firstline == 1 && 9666c359123SMaxim Konovalov (Tflag > 0 || Cflag > 0)) { 9676c359123SMaxim Konovalov /* 9686c359123SMaxim Konovalov * If zflag is set and we did not print any device 9696c359123SMaxim Konovalov * lines I/O because they were all zero, 9706c359123SMaxim Konovalov * print TTY/CPU stats. 9716c359123SMaxim Konovalov */ 9726c359123SMaxim Konovalov printf("%52s",""); 9736c359123SMaxim Konovalov if (Tflag > 0) 9746c359123SMaxim Konovalov printf("%4.0Lf %5.0Lf", cur.tk_nin / etime, 9756c359123SMaxim Konovalov cur.tk_nout / etime); 9766c359123SMaxim Konovalov if (Cflag > 0) 9776c359123SMaxim Konovalov cpustats(); 9786c359123SMaxim Konovalov printf("\n"); 9796c359123SMaxim Konovalov } 980dea673e9SRodney W. Grimes } 981dea673e9SRodney W. Grimes 9828d2fbde5SJustin T. Gibbs static void 9838d2fbde5SJustin T. Gibbs cpustats(void) 984dea673e9SRodney W. Grimes { 98547e065b4SMaxim Konovalov int state; 98601368cfaSAlan Somers double cptime; 987dea673e9SRodney W. Grimes 98801368cfaSAlan Somers cptime = 0.0; 9898d2fbde5SJustin T. Gibbs 990dea673e9SRodney W. Grimes for (state = 0; state < CPUSTATES; ++state) 99101368cfaSAlan Somers cptime += cur.cp_time[state]; 992dea673e9SRodney W. Grimes for (state = 0; state < CPUSTATES; ++state) 9938fa6b8a8SBruce Evans printf(" %2.0f", 99401368cfaSAlan Somers rint(100. * cur.cp_time[state] / (cptime ? cptime : 1))); 995dea673e9SRodney W. Grimes } 9965fc5ae5cSThomas Moestl 9975dc445bfSKenneth D. Merry static int 9985dc445bfSKenneth D. Merry readvar(kvm_t *kd, const char *name, int nlid, void *ptr, size_t len) 9995fc5ae5cSThomas Moestl { 10005dc445bfSKenneth D. Merry if (kd != NULL) { 10015dc445bfSKenneth D. Merry ssize_t nbytes; 10025dc445bfSKenneth D. Merry 10038d56a4caSJohn Baldwin nbytes = kvm_read(kd, namelist[nlid].n_value, ptr, len); 10045dc445bfSKenneth D. Merry 10058d56a4caSJohn Baldwin if (nbytes < 0) { 10068d56a4caSJohn Baldwin warnx("kvm_read(%s): %s", namelist[nlid].n_name, 10078d56a4caSJohn Baldwin kvm_geterr(kd)); 10085dc445bfSKenneth D. Merry return (1); 1009a59c2129SAlan Somers } else if ((size_t)nbytes != len) { 10108d56a4caSJohn Baldwin warnx("kvm_read(%s): expected %zu bytes, got %zd bytes", 10118d56a4caSJohn Baldwin namelist[nlid].n_name, len, nbytes); 10125dc445bfSKenneth D. Merry return (1); 10135dc445bfSKenneth D. Merry } 10145dc445bfSKenneth D. Merry } else { 10155fc5ae5cSThomas Moestl size_t nlen = len; 10165fc5ae5cSThomas Moestl 10175dc445bfSKenneth D. Merry if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) { 10185dc445bfSKenneth D. Merry warn("sysctl(%s...) failed", name); 10195dc445bfSKenneth D. Merry return (1); 10205dc445bfSKenneth D. Merry } 10215dc445bfSKenneth D. Merry if (nlen != len) { 10225dc445bfSKenneth D. Merry warnx("sysctl(%s...): expected %lu, got %lu", name, 10235fc5ae5cSThomas Moestl (unsigned long)len, (unsigned long)nlen); 10245dc445bfSKenneth D. Merry return (1); 10255dc445bfSKenneth D. Merry } 10265dc445bfSKenneth D. Merry } 10275dc445bfSKenneth D. Merry return (0); 10285fc5ae5cSThomas Moestl } 1029