iostat.c (c1a2e93e944800ece4422aeddfc2e5fbe851aed3) | iostat.c (8d2fbde5040bc61a6c4685c0b8db2289834bc353) |
---|---|
1/* 2 * Copyright (c) 1997, 1998 Kenneth D. Merry. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $Id$ 29 */ 30/* 31 * Parts of this program are derived from the original FreeBSD iostat 32 * program: 33 */ |
|
1/*- 2 * Copyright (c) 1986, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 16 unchanged lines hidden (view full) --- 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ | 34/*- 35 * Copyright (c) 1986, 1991, 1993 36 * The Regents of the University of California. All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright --- 16 unchanged lines hidden (view full) --- 58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 * SUCH DAMAGE. 65 */ |
66/* 67 * Ideas for the new iostat statistics output modes taken from the NetBSD 68 * version of iostat: 69 */ 70/* 71 * Copyright (c) 1996 John M. Vinopal 72 * All rights reserved. 73 * 74 * Redistribution and use in source and binary forms, with or without 75 * modification, are permitted provided that the following conditions 76 * are met: 77 * 1. Redistributions of source code must retain the above copyright 78 * notice, this list of conditions and the following disclaimer. 79 * 2. Redistributions in binary form must reproduce the above copyright 80 * notice, this list of conditions and the following disclaimer in the 81 * documentation and/or other materials provided with the distribution. 82 * 3. All advertising materials mentioning features or use of this software 83 * must display the following acknowledgement: 84 * This product includes software developed for the NetBSD Project 85 * by John M. Vinopal. 86 * 4. The name of the author may not be used to endorse or promote products 87 * derived from this software without specific prior written permission. 88 * 89 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 90 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 91 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 92 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 93 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 94 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 95 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 96 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 97 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 98 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 99 * SUCH DAMAGE. 100 */ |
|
33 | 101 |
34#ifndef lint 35static const char copyright[] = 36"@(#) Copyright (c) 1986, 1991, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ | |
39 | 102 |
40#ifndef lint 41#if 0 42static char sccsid[] = "@(#)iostat.c 8.2 (Berkeley) 1/26/94"; 43#endif 44static const char rcsid[] = 45 "$Id$"; 46#endif /* not lint */ 47 | |
48#include <sys/param.h> | 103#include <sys/param.h> |
49#include <sys/buf.h> | 104#include <sys/types.h> 105#include <sys/errno.h> |
50#include <sys/dkstat.h> 51 52#include <err.h> 53#include <ctype.h> 54#include <fcntl.h> 55#include <kvm.h> | 106#include <sys/dkstat.h> 107 108#include <err.h> 109#include <ctype.h> 110#include <fcntl.h> 111#include <kvm.h> |
56#include <limits.h> 57#include <nlist.h> 58#include <paths.h> 59#include <signal.h> | |
60#include <stdio.h> 61#include <stdlib.h> 62#include <string.h> 63#include <unistd.h> | 112#include <stdio.h> 113#include <stdlib.h> 114#include <string.h> 115#include <unistd.h> |
116#include <limits.h> 117#include <devstat.h> |
|
64 65struct nlist namelist[] = { | 118 119struct nlist namelist[] = { |
66#define X_DK_TIME 0 67 { "_dk_time" }, 68#define X_DK_XFER 1 69 { "_dk_xfer" }, 70#define X_DK_WDS 2 71 { "_dk_wds" }, 72#define X_TK_NIN 3 | 120#define X_TK_NIN 0 |
73 { "_tk_nin" }, | 121 { "_tk_nin" }, |
74#define X_TK_NOUT 4 | 122#define X_TK_NOUT 1 |
75 { "_tk_nout" }, | 123 { "_tk_nout" }, |
76#define X_DK_SEEK 5 77 { "_dk_seek" }, 78#define X_CP_TIME 6 | 124#define X_CP_TIME 2 |
79 { "_cp_time" }, | 125 { "_cp_time" }, |
80#define X_DK_WPMS 7 81 { "_dk_wpms" }, 82#define X_HZ 8 | 126#define X_HZ 3 |
83 { "_hz" }, | 127 { "_hz" }, |
84#define X_STATHZ 9 | 128#define X_STATHZ 4 |
85 { "_stathz" }, | 129 { "_stathz" }, |
86#define X_DK_NDRIVE 10 87 { "_dk_ndrive" }, 88#define X_END 10 89#if defined(hp300) || defined(luna68k) 90#define X_HPDINIT (X_END+1) 91 { "_hp_dinit" }, 92#endif 93#if defined(i386) 94#define X_DK_NAMES (X_END+1) 95 { "_dk_names" }, 96#endif 97#ifdef mips 98#define X_SCSI_DINIT (X_END+1) 99 { "_scsi_dinit" }, 100#endif 101#ifdef tahoe 102#define X_VBDINIT (X_END+1) 103 { "_vbdinit" }, 104#endif 105#ifdef vax 106 { "_mbdinit" }, 107#define X_MBDINIT (X_END+1) 108 { "_ubdinit" }, 109#define X_UBDINIT (X_END+2) 110#endif | 130#define X_END 4 |
111 { NULL }, 112}; 113 | 131 { NULL }, 132}; 133 |
114struct _disk { 115 long cp_time[CPUSTATES]; 116 long *dk_time; 117 long *dk_wds; 118 long *dk_seek; 119 long *dk_xfer; 120 long tk_nin; 121 long tk_nout; 122} cur, last; | 134struct statinfo cur, last; 135int num_devices; 136struct device_selection *dev_select; 137int maxshowdevs; 138int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0; |
123 | 139 |
124kvm_t *kd; 125double etime; 126long *dk_wpms; 127int dk_ndrive, *dr_select, hz, kmemfd, ndrives; 128char **dr_name; 129 | |
130#define nlread(x, v) \ 131 kvm_read(kd, namelist[x].n_value, &(v), sizeof(v)) 132 | 140#define nlread(x, v) \ 141 kvm_read(kd, namelist[x].n_value, &(v), sizeof(v)) 142 |
133#include "names.c" /* XXX */ | 143/* local function declarations */ 144static void usage(void); 145static void phdr(int signo); 146static void devstats(int perf_select); 147static void cpustats(void); |
134 | 148 |
135void cpustats __P((void)); 136void dkstats __P((void)); 137void phdr __P((int)); 138static void usage __P((void)); | 149static void 150usage(void) 151{ 152 /* 153 * We also support the following 'traditional' syntax: 154 * iostat [drives] [wait [count]] 155 * This isn't mentioned in the man page, or the usage statement, 156 * but it is supported. 157 */ 158 fprintf(stderr, "usage: iostat [-CdhIoT?] [-c count] [-M core]" 159 " [-n devs] [-N system]\n" 160 "\t [-t type,if,pass] [-w wait] [drives]\n"); 161} |
139 140int | 162 163int |
141main(argc, argv) 142 int argc; 143 char *argv[]; | 164main(int argc, char **argv) |
144{ | 165{ |
166 int c; |
|
145 register int i; | 167 register int i; |
146 long tmp; 147 int ch, hdrcnt, reps, interval, stathz, ndrives; 148 char **cp, *memf, *nlistf, buf[30]; | 168 int tflag = 0, hflag = 0, cflag = 0, wflag = 0, nflag = 0; 169 int count = 0, waittime = 0; 170 char *memf = NULL, *nlistf = NULL; 171 struct devstat_match *matches; 172 int num_matches = 0; |
149 char errbuf[_POSIX2_LINE_MAX]; | 173 char errbuf[_POSIX2_LINE_MAX]; |
174 char *err_str; 175 kvm_t *kd; 176 int hz, stathz; 177 int headercount; 178 int generation; 179 int num_devices_specified; 180 int num_selected, num_selections, select_generation; 181 char **specified_devices; 182 devstat_select_mode select_mode; |
|
150 | 183 |
151 interval = reps = 0; 152 nlistf = memf = NULL; 153 while ((ch = getopt(argc, argv, "c:M:N:w:")) != -1) 154 switch(ch) { 155 case 'c': 156 if ((reps = atoi(optarg)) <= 0) 157 errx(1, "repetition count <= 0"); 158 break; 159 case 'M': 160 memf = optarg; 161 break; 162 case 'N': 163 nlistf = optarg; 164 break; 165 case 'w': 166 if ((interval = atoi(optarg)) <= 0) 167 errx(1, "interval <= 0"); 168 break; 169 case '?': 170 default: 171 usage(); | 184 matches = NULL; 185 maxshowdevs = 3; 186 187 while ((c = getopt(argc, argv, "c:CdhIM:n:N:ot:Tw:?")) != -1) { 188 switch(c) { 189 case 'c': 190 cflag++; 191 count = atoi(optarg); 192 if (count < 1) 193 errx(1, "count %d is < 1", count); 194 break; 195 case 'C': 196 Cflag++; 197 break; 198 case 'd': 199 dflag++; 200 break; 201 case 'h': 202 hflag++; 203 break; 204 case 'I': 205 Iflag++; 206 break; 207 case 'M': 208 memf = optarg; 209 break; 210 case 'n': 211 nflag++; 212 maxshowdevs = atoi(optarg); 213 if (maxshowdevs < 0) 214 errx(1, "number of devcies %d is < 0", 215 maxshowdevs); 216 break; 217 case 'N': 218 nlistf = optarg; 219 break; 220 case 'o': 221 oflag++; 222 break; 223 case 't': 224 tflag++; 225 if (buildmatch(optarg, &matches, 226 &num_matches) != 0) 227 errx(1, "%s", devstat_errbuf); 228 break; 229 case 'T': 230 Tflag++; 231 break; 232 case 'w': 233 wflag++; 234 waittime = atoi(optarg); 235 if (waittime < 1) 236 errx(1, "wait time is < 1"); 237 break; 238 default: 239 usage(); 240 exit(1); 241 break; |
172 } | 242 } |
243 } 244 |
|
173 argc -= optind; 174 argv += optind; 175 176 /* 177 * Discard setgid privileges if not the running kernel so that bad 178 * guys can't print interesting stuff from kernel memory. 179 */ 180 if (nlistf != NULL || memf != NULL) 181 setgid(getgid()); 182 | 245 argc -= optind; 246 argv += optind; 247 248 /* 249 * Discard setgid privileges if not the running kernel so that bad 250 * guys can't print interesting stuff from kernel memory. 251 */ 252 if (nlistf != NULL || memf != NULL) 253 setgid(getgid()); 254 |
183 kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 184 if (kd == 0) 185 errx(1, "kvm_openfiles: %s", errbuf); 186 if (kvm_nlist(kd, namelist) == -1) 187 errx(1, "kvm_nlist: %s", kvm_geterr(kd)); 188 if (namelist[X_DK_NDRIVE].n_type == 0) 189 errx(1, "dk_ndrive not found in namelist"); 190 (void)nlread(X_DK_NDRIVE, dk_ndrive); 191 if (dk_ndrive < 0) 192 errx(1, "invalid dk_ndrive %d", dk_ndrive); | 255 /* 256 * Make sure that the userland devstat version matches the kernel 257 * devstat version. If not, exit and print a message informing 258 * the user of his mistake. 259 */ 260 if (checkversion() < 0) 261 errx(1, "%s", devstat_errbuf); |
193 | 262 |
194 cur.dk_time = calloc(dk_ndrive, sizeof(long)); 195 cur.dk_wds = calloc(dk_ndrive, sizeof(long)); 196 cur.dk_seek = calloc(dk_ndrive, sizeof(long)); 197 cur.dk_xfer = calloc(dk_ndrive, sizeof(long)); 198 last.dk_time = calloc(dk_ndrive, sizeof(long)); 199 last.dk_wds = calloc(dk_ndrive, sizeof(long)); 200 last.dk_seek = calloc(dk_ndrive, sizeof(long)); 201 last.dk_xfer = calloc(dk_ndrive, sizeof(long)); 202 dr_select = calloc(dk_ndrive, sizeof(int)); 203 dr_name = calloc(dk_ndrive, sizeof(char *)); 204 dk_wpms = calloc(dk_ndrive, sizeof(long)); 205 206 for (i = 0; i < dk_ndrive; i++) { 207 (void)sprintf(buf, "dk%d", i); 208 dr_name[i] = strdup(buf); | 263 /* 264 * Figure out how many devices we should display. 265 */ 266 if (nflag == 0) { 267 if (oflag > 0) { 268 if ((dflag > 0) && (Cflag == 0) && (Tflag == 0)) 269 maxshowdevs = 5; 270 else if ((dflag > 0) && (Tflag > 0) && (Cflag == 0)) 271 maxshowdevs = 5; 272 else 273 maxshowdevs = 4; 274 } else { 275 if ((dflag > 0) && (Cflag == 0)) 276 maxshowdevs = 4; 277 else 278 maxshowdevs = 3; 279 } |
209 } | 280 } |
210 if (!read_names()) 211 exit(1); 212 (void)nlread(X_HZ, hz); 213 (void)nlread(X_STATHZ, stathz); 214 if (stathz) 215 hz = stathz; 216 (void)kvm_read(kd, namelist[X_DK_WPMS].n_value, dk_wpms, 217 dk_ndrive * sizeof(dk_wpms)); | |
218 | 281 |
282 /* find out how many devices we have */ 283 if ((num_devices = getnumdevs()) < 0) 284 err(1, "can't get number of devices"); 285 286 cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo)); 287 last.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo)); 288 bzero(cur.dinfo, sizeof(struct devinfo)); 289 bzero(last.dinfo, sizeof(struct devinfo)); 290 |
|
219 /* | 291 /* |
220 * Choose drives to be displayed. Priority goes to (in order) drives 221 * supplied as arguments and default drives. If everything isn't 222 * filled in and there are drives not taken care of, display the first 223 * few that fit. 224 * 225 * The backward compatibility #ifdefs permit the syntax: 226 * iostat [ drives ] [ interval [ count ] ] | 292 * Grab all the devices. We don't look to see if the list has 293 * changed here, since it almost certainly has. We only look for 294 * errors. |
227 */ | 295 */ |
228#define BACKWARD_COMPATIBILITY 229 for (ndrives = 0; *argv; ++argv) { 230#ifdef BACKWARD_COMPATIBILITY | 296 if (getdevs(&cur) == -1) 297 errx(1, "%s", devstat_errbuf); 298 299 num_devices = cur.dinfo->numdevs; 300 generation = cur.dinfo->generation; 301 302 /* 303 * If the user specified any devices on the command line, see if 304 * they are in the list of devices we have now. 305 */ 306 specified_devices = (char **)malloc(sizeof(char *)); 307 for (num_devices_specified = 0; *argv; ++argv) { |
231 if (isdigit(**argv)) 232 break; | 308 if (isdigit(**argv)) 309 break; |
233#endif 234 for (i = 0; i < dk_ndrive; i++) { 235 if (strcmp(dr_name[i], *argv)) 236 continue; 237 dr_select[i] = 1; 238 ++ndrives; 239 } | 310 num_devices_specified++; 311 specified_devices = (char **)realloc(specified_devices, 312 sizeof(char *) * 313 num_devices_specified); 314 specified_devices[num_devices_specified - 1] = *argv; 315 |
240 } | 316 } |
241#ifdef BACKWARD_COMPATIBILITY | 317 318 dev_select = NULL; 319 320 if ((num_devices_specified == 0) && (num_matches == 0)) 321 select_mode = DS_SELECT_ADD; 322 else 323 select_mode = DS_SELECT_ONLY; 324 325 /* 326 * At this point, selectdevs will almost surely indicate that the 327 * device list has changed, so we don't look for return values of 0 328 * or 1. If we get back -1, though, there is an error. 329 */ 330 if (selectdevs(&dev_select, &num_selected, 331 &num_selections, &select_generation, 332 generation, cur.dinfo->devices, num_devices, 333 matches, num_matches, 334 specified_devices, num_devices_specified, 335 select_mode, maxshowdevs, hflag) == -1) 336 errx(1, "%s", devstat_errbuf); 337 338 free(specified_devices); 339 340 /* 341 * Look for the traditional wait time and count arguments. 342 */ |
242 if (*argv) { | 343 if (*argv) { |
243 interval = atoi(*argv); 244 if (*++argv) 245 reps = atoi(*argv); 246 } 247#endif | 344 waittime = atoi(*argv); |
248 | 345 |
249 if (interval) { 250 if (!reps) 251 reps = -1; 252 } else 253 if (reps) 254 interval = 1; | 346 /* Let the user know he goofed, but keep going anyway */ 347 if (wflag != 0) 348 warnx("discarding previous wait interval, using" 349 " %d instead", waittime); 350 wflag++; |
255 | 351 |
256 for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 257 if (dr_select[i] || dk_wpms[i] == 0) 258 continue; 259 for (cp = defdrives; *cp; cp++) 260 if (strcmp(dr_name[i], *cp) == 0) { 261 dr_select[i] = 1; 262 ++ndrives; 263 break; 264 } | 352 if (*++argv) { 353 count = atoi(*argv); 354 if (cflag != 0) 355 warnx("discarding previous count, using %d" 356 " instead", count); 357 cflag++; 358 } else 359 count = -1; |
265 } | 360 } |
266 for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 267 if (dr_select[i]) 268 continue; 269 dr_select[i] = 1; 270 ++ndrives; 271 } | |
272 | 361 |
362 /* 363 * If the user specified a count, but not an interval, we default 364 * to an interval of 1 second. 365 */ 366 if ((wflag == 0) && (cflag > 0)) 367 waittime = 1; 368 369 /* 370 * If the user specified a wait time, but not a count, we want to 371 * go on ad infinitum. This can be redundant if the user uses the 372 * traditional method of specifying the wait, since in that case we 373 * already set count = -1 above. Oh well. 374 */ 375 if ((wflag > 0) && (cflag == 0)) 376 count = -1; 377 378 kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 379 380 if (kd == 0) 381 errx(1, "kvm_openfiles: %s", errbuf); 382 383 if (kvm_nlist(kd, namelist) == -1) 384 errx(1, "kvm_nlist: %s", kvm_geterr(kd)); 385 386 (void)nlread(X_HZ, hz); 387 (void)nlread(X_STATHZ, stathz); 388 if (stathz) 389 hz = stathz; 390 391 /* 392 * If the user stops the program (control-Z) and then resumes it, 393 * print out the header again. 394 */ |
|
273 (void)signal(SIGCONT, phdr); 274 | 395 (void)signal(SIGCONT, phdr); 396 |
275 for (hdrcnt = 1;;) { 276 if (!--hdrcnt) { | 397 for (headercount = 1;;) { 398 struct devinfo *tmp_dinfo; 399 long tmp; 400 double etime; 401 402 if (!--headercount) { |
277 phdr(0); | 403 phdr(0); |
278 hdrcnt = 20; | 404 headercount = 20; |
279 } | 405 } |
280 (void)kvm_read(kd, namelist[X_DK_TIME].n_value, 281 cur.dk_time, dk_ndrive * sizeof(long)); 282 (void)kvm_read(kd, namelist[X_DK_XFER].n_value, 283 cur.dk_xfer, dk_ndrive * sizeof(long)); 284 (void)kvm_read(kd, namelist[X_DK_WDS].n_value, 285 cur.dk_wds, dk_ndrive * sizeof(long)); 286 (void)kvm_read(kd, namelist[X_DK_SEEK].n_value, 287 cur.dk_seek, dk_ndrive * sizeof(long)); | |
288 (void)kvm_read(kd, namelist[X_TK_NIN].n_value, 289 &cur.tk_nin, sizeof(cur.tk_nin)); 290 (void)kvm_read(kd, namelist[X_TK_NOUT].n_value, 291 &cur.tk_nout, sizeof(cur.tk_nout)); 292 (void)kvm_read(kd, namelist[X_CP_TIME].n_value, 293 cur.cp_time, sizeof(cur.cp_time)); | 406 (void)kvm_read(kd, namelist[X_TK_NIN].n_value, 407 &cur.tk_nin, sizeof(cur.tk_nin)); 408 (void)kvm_read(kd, namelist[X_TK_NOUT].n_value, 409 &cur.tk_nout, sizeof(cur.tk_nout)); 410 (void)kvm_read(kd, namelist[X_CP_TIME].n_value, 411 cur.cp_time, sizeof(cur.cp_time)); |
294 for (i = 0; i < dk_ndrive; i++) { 295 if (!dr_select[i]) 296 continue; 297#define X(fld) tmp = cur.fld[i]; cur.fld[i] -= last.fld[i]; last.fld[i] = tmp 298 X(dk_xfer); 299 X(dk_seek); 300 X(dk_wds); 301 X(dk_time); | 412 413 tmp_dinfo = last.dinfo; 414 last.dinfo = cur.dinfo; 415 cur.dinfo = tmp_dinfo; 416 417 last.busy_time = cur.busy_time; 418 419 /* 420 * Here what we want to do is refresh our device stats. 421 * getdevs() returns 1 when the device list has changed. 422 * If the device list has changed, we want to go through 423 * the selection process again, in case a device that we 424 * were previously displaying has gone away. 425 */ 426 switch (getdevs(&cur)) { 427 case -1: 428 errx(1, "%s", devstat_errbuf); 429 break; 430 case 1: { 431 int retval; 432 433 num_devices = cur.dinfo->numdevs; 434 generation = cur.dinfo->generation; 435 retval = selectdevs(&dev_select, &num_selected, 436 &num_selections, &select_generation, 437 generation, cur.dinfo->devices, 438 num_devices, matches, num_matches, 439 specified_devices, 440 num_devices_specified, 441 select_mode, maxshowdevs, hflag); 442 switch(retval) { 443 case -1: 444 errx(1, "%s", devstat_errbuf); 445 break; 446 case 1: 447 phdr(0); 448 headercount = 20; 449 break; 450 default: 451 break; 452 } 453 break; |
302 } | 454 } |
455 default: 456 break; 457 } 458 459 /* 460 * We only want to re-select devices if we're in 'top' 461 * mode. This is the only mode where the devices selected 462 * could actually change. 463 */ 464 if (hflag > 0) { 465 int retval; 466 retval = selectdevs(&dev_select, &num_selected, 467 &num_selections, &select_generation, 468 generation, cur.dinfo->devices, 469 num_devices, matches, num_matches, 470 specified_devices, 471 num_devices_specified, 472 select_mode, maxshowdevs, hflag); 473 switch(retval) { 474 case -1: 475 errx(1,"%s", devstat_errbuf); 476 break; 477 case 1: 478 phdr(0); 479 headercount = 20; 480 break; 481 default: 482 break; 483 } 484 } 485 |
|
303 tmp = cur.tk_nin; 304 cur.tk_nin -= last.tk_nin; 305 last.tk_nin = tmp; 306 tmp = cur.tk_nout; 307 cur.tk_nout -= last.tk_nout; 308 last.tk_nout = tmp; | 486 tmp = cur.tk_nin; 487 cur.tk_nin -= last.tk_nin; 488 last.tk_nin = tmp; 489 tmp = cur.tk_nout; 490 cur.tk_nout -= last.tk_nout; 491 last.tk_nout = tmp; |
309 etime = 0; | 492 493 etime = 0.0; 494 495#define X(fld) tmp = cur.fld[i]; cur.fld[i] -= last.fld[i]; last.fld[i] = tmp 496 |
310 for (i = 0; i < CPUSTATES; i++) { 311 X(cp_time); 312 etime += cur.cp_time[i]; 313 } 314 if (etime == 0.0) 315 etime = 1.0; 316 etime /= (float)hz; | 497 for (i = 0; i < CPUSTATES; i++) { 498 X(cp_time); 499 etime += cur.cp_time[i]; 500 } 501 if (etime == 0.0) 502 etime = 1.0; 503 etime /= (float)hz; |
317 (void)printf("%4.0f%5.0f", 318 cur.tk_nin / etime, cur.tk_nout / etime); 319 dkstats(); 320 cpustats(); 321 (void)printf("\n"); 322 (void)fflush(stdout); | 504 if ((dflag == 0) || (Tflag > 0)) 505 printf("%4.0f%5.0f", cur.tk_nin / etime, 506 cur.tk_nout/etime); 507 devstats(hflag); 508 if ((dflag == 0) || (Cflag > 0)) 509 cpustats(); 510 printf("\n"); 511 fflush(stdout); |
323 | 512 |
324 if (reps >= 0 && --reps <= 0) | 513 if (count >= 0 && --count <= 0) |
325 break; | 514 break; |
326 (void)sleep(interval); | 515 516 sleep(waittime); |
327 } | 517 } |
518 |
|
328 exit(0); 329} 330 | 519 exit(0); 520} 521 |
331/* ARGUSED */ 332void 333phdr(signo) 334 int signo; | 522static void 523phdr(int signo) |
335{ 336 register int i; | 524{ 525 register int i; |
526 int printed; |
|
337 | 527 |
338 (void)printf(" tty"); 339 for (i = 0; i < dk_ndrive; i++) 340 if (dr_select[i]) 341 (void)printf(" %4.4s ", dr_name[i]); 342 (void)printf(" cpu\n tin tout"); 343 for (i = 0; i < dk_ndrive; i++) 344 if (dr_select[i]) 345 (void)printf(" sps tps msps "); 346 (void)printf(" us ni sy in id\n"); | 528 if ((dflag == 0) || (Tflag > 0)) 529 (void)printf(" tty"); 530 for (i = 0, printed=0;(i < num_devices) && (printed < maxshowdevs);i++){ 531 int di; 532 if ((dev_select[i].selected != 0) 533 && (dev_select[i].selected <= maxshowdevs)) { 534 di = dev_select[i].position; 535 if (oflag > 0) 536 (void)printf("%12.6s%d ", 537 cur.dinfo->devices[di].device_name, 538 cur.dinfo->devices[di].unit_number); 539 else 540 printf("%15.6s%d ", 541 cur.dinfo->devices[di].device_name, 542 cur.dinfo->devices[di].unit_number); 543 printed++; 544 } 545 } 546 if ((dflag == 0) || (Cflag > 0)) 547 (void)printf(" cpu\n"); 548 else 549 (void)printf("\n"); 550 551 if ((dflag == 0) || (Tflag > 0)) 552 (void)printf(" tin tout"); 553 554 for (i=0, printed = 0;(i < num_devices) && (printed < maxshowdevs);i++){ 555 if ((dev_select[i].selected != 0) 556 && (dev_select[i].selected <= maxshowdevs)) { 557 if (oflag > 0) 558 if (Iflag == 0) 559 (void)printf(" sps tps msps "); 560 else 561 (void)printf(" blk xfr msps "); 562 563 else 564 if (Iflag == 0) 565 printf(" KB/t tps MB/s "); 566 else 567 printf(" KB/t xfrs MB "); 568 printed++; 569 } 570 } 571 if ((dflag == 0) || (Cflag > 0)) 572 (void)printf(" us ni sy in id\n"); 573 else 574 printf("\n"); 575 |
347} 348 | 576} 577 |
349void 350dkstats() | 578static void 579devstats(int perf_select) |
351{ 352 register int dn; | 580{ 581 register int dn; |
353 double atime, itime, msps, words, xtime; | 582 long double transfers_per_second; 583 long double kb_per_transfer, mb_per_second; 584 u_int64_t total_bytes, total_transfers, total_blocks; 585 long double busy_seconds; 586 long double total_mb; 587 long double blocks_per_second, ms_per_transaction; 588 589 /* 590 * Calculate elapsed time up front, since it's the same for all 591 * devices. 592 */ 593 busy_seconds = compute_etime(cur.busy_time, last.busy_time); |
354 | 594 |
355 for (dn = 0; dn < dk_ndrive; ++dn) { 356 if (!dr_select[dn]) | 595 for (dn = 0; dn < num_devices; dn++) { 596 int di; 597 598 if (((perf_select == 0) && (dev_select[dn].selected == 0)) 599 || (dev_select[dn].selected > maxshowdevs)) |
357 continue; | 600 continue; |
358 words = (double)cur.dk_wds[dn] * 32; /* words xfer'd */ 359 (void)printf("%4.0f", /* sectors */ 360 words / (DEV_BSIZE / 2) / etime); | |
361 | 601 |
362 (void)printf("%4.0f", cur.dk_xfer[dn] / etime); | 602 di = dev_select[dn].position; |
363 | 603 |
364 if (dk_wpms[dn] && cur.dk_xfer[dn]) { 365 atime = cur.dk_time[dn]; /* ticks disk busy */ 366 atime /= (float)hz; /* ticks to seconds */ 367 xtime = words / dk_wpms[dn]; /* transfer time */ 368 itime = atime - xtime; /* time not xfer'ing */ 369 if (itime < 0) 370 msps = 0; 371 else 372 msps = itime * 1000 / cur.dk_xfer[dn]; 373 } else 374 msps = 0; 375 (void)printf("%5.1f ", msps); | 604 if (compute_stats(&cur.dinfo->devices[di], 605 &last.dinfo->devices[di], busy_seconds, 606 &total_bytes, &total_transfers, 607 &total_blocks, &kb_per_transfer, 608 &transfers_per_second, &mb_per_second, 609 &blocks_per_second, &ms_per_transaction)!= 0) 610 errx(1, "%s", devstat_errbuf); 611 612 if (perf_select != 0) { 613 dev_select[dn].bytes = total_bytes; 614 if ((dev_select[dn].selected == 0) 615 || (dev_select[dn].selected > maxshowdevs)) 616 continue; 617 } 618 619 if (oflag > 0) { 620 621 if (Iflag == 0) 622 printf("%4.0Lf%4.0Lf%5.1Lf ", 623 blocks_per_second, 624 transfers_per_second, 625 ms_per_transaction); 626 else 627 printf("%4.1qu%4.1qu%5.1Lf ", 628 total_blocks, 629 total_transfers, 630 ms_per_transaction); 631 } else { 632 633 if (Iflag == 0) 634 printf(" %5.2Lf %3.0Lf %5.2Lf ", 635 kb_per_transfer, 636 transfers_per_second, 637 mb_per_second); 638 else { 639 total_mb = total_bytes; 640 total_mb /= 1024 * 1024; 641 642 printf(" %5.2Lf %3.1qu %5.2Lf ", 643 kb_per_transfer, 644 total_transfers, 645 total_mb); 646 } 647 } |
376 } 377} 378 | 648 } 649} 650 |
379void 380cpustats() | 651static void 652cpustats(void) |
381{ 382 register int state; 383 double time; 384 | 653{ 654 register int state; 655 double time; 656 |
385 time = 0; | 657 time = 0.0; 658 |
386 for (state = 0; state < CPUSTATES; ++state) 387 time += cur.cp_time[state]; 388 for (state = 0; state < CPUSTATES; ++state) | 659 for (state = 0; state < CPUSTATES; ++state) 660 time += cur.cp_time[state]; 661 for (state = 0; state < CPUSTATES; ++state) |
389 (void)printf("%3.0f", 390 100. * cur.cp_time[state] / (time ? time : 1)); | 662 printf("%3.0f", 663 100. * cur.cp_time[state] / (time ? time : 1)); |
391} | 664} |
392 393static void 394usage() 395{ 396 (void)fprintf(stderr, 397"usage: iostat [-c count] [-M core] [-N system] [-w wait] [drives]\n"); 398 exit(1); 399} | |