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 * $FreeBSD: src/usr.sbin/iostat/iostat.c,v 1.17.2.2 2001/07/19 04:15:42 kris Exp $ 29 * $DragonFly: src/usr.sbin/iostat/iostat.c,v 1.7 2005/09/01 19:08:38 swildner Exp $ 30 */ 31 /* 32 * Parts of this program are derived from the original FreeBSD iostat 33 * program: 34 */ 35 /*- 36 * Copyright (c) 1986, 1991, 1993 37 * The Regents of the University of California. All rights reserved. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. Neither the name of the University nor the names of its contributors 48 * may be used to endorse or promote products derived from this software 49 * without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 */ 63 /* 64 * Ideas for the new iostat statistics output modes taken from the NetBSD 65 * version of iostat: 66 */ 67 /* 68 * Copyright (c) 1996 John M. Vinopal 69 * All rights reserved. 70 * 71 * Redistribution and use in source and binary forms, with or without 72 * modification, are permitted provided that the following conditions 73 * are met: 74 * 1. Redistributions of source code must retain the above copyright 75 * notice, this list of conditions and the following disclaimer. 76 * 2. Redistributions in binary form must reproduce the above copyright 77 * notice, this list of conditions and the following disclaimer in the 78 * documentation and/or other materials provided with the distribution. 79 * 3. All advertising materials mentioning features or use of this software 80 * must display the following acknowledgement: 81 * This product includes software developed for the NetBSD Project 82 * by John M. Vinopal. 83 * 4. The name of the author may not be used to endorse or promote products 84 * derived from this software without specific prior written permission. 85 * 86 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 87 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 88 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 89 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 90 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 91 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 92 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 93 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 94 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 95 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 96 * SUCH DAMAGE. 97 */ 98 99 #include <sys/user.h> 100 #include <sys/param.h> 101 #include <sys/errno.h> 102 #include <sys/ttycom.h> 103 104 #include <err.h> 105 #include <ctype.h> 106 #include <fcntl.h> 107 #include <kinfo.h> 108 #include <stdio.h> 109 #include <stdlib.h> 110 #include <string.h> 111 #include <unistd.h> 112 #include <limits.h> 113 #include <devstat.h> 114 115 struct statinfo cur, last; 116 uint64_t tk_nin, old_tk_nin, diff_tk_nin; 117 uint64_t tk_nout, old_tk_nout, diff_tk_nout; 118 struct kinfo_cputime cp_time, old_cp_time, diff_cp_time; 119 double cp_time_total; 120 int num_devices; 121 struct device_selection *dev_select; 122 int maxshowdevs; 123 int dflag = 0, Dflag=0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0; 124 125 /* local function declarations */ 126 static void usage(void); 127 static void phdr(int signo); 128 static void devstats(int perf_select); 129 static void cpustats(void); 130 static void adddeletion(const char *prefix, 131 int num_selected, char ***deletions, int *num_deletions); 132 133 static void 134 usage(void) 135 { 136 /* 137 * We also support the following 'traditional' syntax: 138 * iostat [drives] [wait [count]] 139 * This isn't mentioned in the man page, or the usage statement, 140 * but it is supported. 141 */ 142 fprintf(stderr, "usage: iostat [-CdhIKoT] [-c count]" 143 " [-n devs]\n" 144 "\t [-t type,if,pass] [-w wait] [drives]\n"); 145 } 146 147 int 148 main(int argc, char **argv) 149 { 150 int c; 151 int tflag = 0, hflag = 0, cflag = 0, wflag = 0, nflag = 0; 152 int count = 0, waittime = 0; 153 struct devstat_match *matches; 154 int num_matches = 0; 155 int num_deletions = 0; 156 int hz; 157 int headercount; 158 long generation; 159 int num_devices_specified; 160 int num_selected, num_selections; 161 long select_generation; 162 char **deletions; 163 char **specified_devices; 164 devstat_select_mode select_mode; 165 166 matches = NULL; 167 deletions = NULL; 168 maxshowdevs = 3; 169 170 while ((c = getopt(argc, argv, "c:CdDhIKM:n:N:ot:Tw:")) != -1) { 171 switch(c) { 172 case 'c': 173 cflag++; 174 count = atoi(optarg); 175 if (count < 1) 176 errx(1, "count %d is < 1", count); 177 break; 178 case 'C': 179 Cflag++; 180 break; 181 case 'd': 182 dflag++; 183 break; 184 case 'D': 185 Dflag++; 186 break; 187 case 'h': 188 hflag++; 189 break; 190 case 'I': 191 Iflag++; 192 break; 193 case 'K': 194 Kflag++; 195 break; 196 case 'n': 197 nflag++; 198 maxshowdevs = atoi(optarg); 199 if (maxshowdevs < 0) 200 errx(1, "number of devices %d is < 0", 201 maxshowdevs); 202 break; 203 case 'o': 204 oflag++; 205 break; 206 case 't': 207 tflag++; 208 if (buildmatch(optarg, &matches, 209 &num_matches) != 0) 210 errx(1, "%s", devstat_errbuf); 211 break; 212 case 'T': 213 Tflag++; 214 break; 215 case 'w': 216 wflag++; 217 waittime = atoi(optarg); 218 if (waittime < 1) 219 errx(1, "wait time is < 1"); 220 break; 221 default: 222 usage(); 223 exit(1); 224 break; 225 } 226 } 227 228 argc -= optind; 229 argv += optind; 230 231 /* 232 * Make sure that the userland devstat version matches the kernel 233 * devstat version. If not, exit and print a message informing 234 * the user of his mistake. 235 */ 236 if (checkversion() < 0) 237 errx(1, "%s", devstat_errbuf); 238 239 /* 240 * Figure out how many devices we should display. 241 */ 242 if (nflag == 0) { 243 struct winsize ws; 244 245 if (oflag > 0) { 246 if ((dflag > 0) && (Cflag == 0) && (Tflag == 0)) 247 maxshowdevs = 5; 248 else if ((dflag > 0) && (Tflag > 0) && (Cflag == 0)) 249 maxshowdevs = 5; 250 else 251 maxshowdevs = 4; 252 } else { 253 if ((dflag > 0) && (Cflag == 0)) 254 maxshowdevs = 4; 255 else 256 maxshowdevs = 3; 257 } 258 if (ioctl(1, TIOCGWINSZ, &ws) >= 0 && ws.ws_col > 80) 259 maxshowdevs += (ws.ws_col - 80) / 17; 260 } 261 262 /* find out how many devices we have */ 263 if ((num_devices = getnumdevs()) < 0) 264 err(1, "can't get number of devices"); 265 266 if ((cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo))) == 267 NULL) 268 err(1, "devinfo malloc failed"); 269 if ((last.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo))) == 270 NULL) 271 err(1, "devinfo malloc failed"); 272 bzero(cur.dinfo, sizeof(struct devinfo)); 273 bzero(last.dinfo, sizeof(struct devinfo)); 274 275 /* 276 * Grab all the devices. We don't look to see if the list has 277 * changed here, since it almost certainly has. We only look for 278 * errors. 279 */ 280 if (getdevs(&cur) == -1) 281 errx(1, "%s", devstat_errbuf); 282 283 num_devices = cur.dinfo->numdevs; 284 generation = cur.dinfo->generation; 285 286 /* 287 * If the user specified any devices on the command line, see if 288 * they are in the list of devices we have now. 289 */ 290 if ((specified_devices = (char **)malloc(sizeof(char *))) == NULL) 291 err(1, "specified_devices malloc failed"); 292 for (num_devices_specified = 0; *argv; ++argv) { 293 if (isdigit(**argv)) 294 break; 295 num_devices_specified++; 296 specified_devices = (char **)realloc(specified_devices, 297 sizeof(char *) * 298 num_devices_specified); 299 specified_devices[num_devices_specified - 1] = *argv; 300 301 } 302 if (nflag == 0 && maxshowdevs < num_devices_specified) 303 maxshowdevs = num_devices_specified; 304 305 dev_select = NULL; 306 307 if ((num_devices_specified == 0) && (num_matches == 0)) 308 select_mode = DS_SELECT_ADD; 309 else 310 select_mode = DS_SELECT_ONLY; 311 312 /* 313 * At this point, selectdevs will almost surely indicate that the 314 * device list has changed, so we don't look for return values of 0 315 * or 1. If we get back -1, though, there is an error. 316 */ 317 if (selectdevs(&dev_select, &num_selected, 318 &num_selections, &select_generation, 319 generation, cur.dinfo->devices, num_devices, 320 matches, num_matches, 321 specified_devices, num_devices_specified, 322 select_mode, maxshowdevs, hflag) == -1) { 323 errx(1, "%s", devstat_errbuf); 324 } 325 326 /* 327 * These devices are not usually desired 328 */ 329 if (select_mode == DS_SELECT_ADD) { 330 adddeletion("md", num_selected, &deletions, &num_deletions); 331 adddeletion("pass", num_selected, &deletions, &num_deletions); 332 adddeletion("sg", num_selected, &deletions, &num_deletions); 333 if (selectdevs(&dev_select, &num_selected, 334 &num_selections, &select_generation, 335 generation, cur.dinfo->devices, num_devices, 336 matches, num_matches, 337 deletions, num_deletions, 338 DS_SELECT_REMOVE, maxshowdevs, hflag) == -1) { 339 errx(1, "%s", devstat_errbuf); 340 } 341 select_mode = DS_SELECT_ADDONLY; 342 } 343 344 /* 345 * Look for the traditional wait time and count arguments. 346 */ 347 if (*argv) { 348 waittime = atoi(*argv); 349 350 /* Let the user know he goofed, but keep going anyway */ 351 if (wflag != 0) 352 warnx("discarding previous wait interval, using" 353 " %d instead", waittime); 354 wflag++; 355 356 if (*++argv) { 357 count = atoi(*argv); 358 if (cflag != 0) 359 warnx("discarding previous count, using %d" 360 " instead", count); 361 cflag++; 362 } else 363 count = -1; 364 } 365 366 /* 367 * If the user specified a count, but not an interval, we default 368 * to an interval of 1 second. 369 */ 370 if ((wflag == 0) && (cflag > 0)) 371 waittime = 1; 372 373 /* 374 * If the user specified a wait time, but not a count, we want to 375 * go on ad infinitum. This can be redundant if the user uses the 376 * traditional method of specifying the wait, since in that case we 377 * already set count = -1 above. Oh well. 378 */ 379 if ((wflag > 0) && (cflag == 0)) 380 count = -1; 381 382 if (kinfo_get_sched_hz(&hz)) 383 err(1, "kinfo_get_sched_hz"); 384 if (kinfo_get_sched_stathz(&hz)) 385 err(1, "kinfo_get_sched_stathz"); 386 387 /* 388 * If the user stops the program (control-Z) and then resumes it, 389 * print out the header again. 390 */ 391 signal(SIGCONT, phdr); 392 393 for (headercount = 1;;) { 394 struct devinfo *tmp_dinfo; 395 396 if (!--headercount) { 397 phdr(0); 398 headercount = 20; 399 } 400 if (kinfo_get_tty_tk_nin(&tk_nin)) 401 err(1, "kinfo_get_tty_tk_nin"); 402 if (kinfo_get_tty_tk_nout(&tk_nout)) 403 err(1, "kinfo_get_tty_tk_nout"); 404 if (kinfo_get_sched_cputime(&cp_time)) 405 err(1, "kinfo_get_sched_cputime"); 406 407 tmp_dinfo = last.dinfo; 408 last.dinfo = cur.dinfo; 409 cur.dinfo = tmp_dinfo; 410 411 last.busy_time = cur.busy_time; 412 413 /* 414 * Here what we want to do is refresh our device stats. 415 * getdevs() returns 1 when the device list has changed. 416 * If the device list has changed, we want to go through 417 * the selection process again, in case a device that we 418 * were previously displaying has gone away. 419 */ 420 switch (getdevs(&cur)) { 421 case -1: 422 errx(1, "%s", devstat_errbuf); 423 break; 424 case 1: { 425 int retval; 426 427 num_devices = cur.dinfo->numdevs; 428 generation = cur.dinfo->generation; 429 retval = selectdevs(&dev_select, &num_selected, 430 &num_selections, &select_generation, 431 generation, cur.dinfo->devices, 432 num_devices, matches, num_matches, 433 specified_devices, 434 num_devices_specified, 435 select_mode, maxshowdevs, hflag); 436 switch(retval) { 437 case -1: 438 errx(1, "%s", devstat_errbuf); 439 break; 440 case 1: 441 phdr(0); 442 headercount = 20; 443 break; 444 default: 445 break; 446 } 447 break; 448 } 449 default: 450 break; 451 } 452 453 /* 454 * We only want to re-select devices if we're in 'top' 455 * mode. This is the only mode where the devices selected 456 * could actually change. 457 */ 458 if (hflag > 0) { 459 int retval; 460 retval = selectdevs(&dev_select, &num_selected, 461 &num_selections, &select_generation, 462 generation, cur.dinfo->devices, 463 num_devices, matches, num_matches, 464 specified_devices, 465 num_devices_specified, 466 select_mode, maxshowdevs, hflag); 467 switch(retval) { 468 case -1: 469 errx(1,"%s", devstat_errbuf); 470 break; 471 case 1: 472 phdr(0); 473 headercount = 20; 474 break; 475 default: 476 break; 477 } 478 } 479 480 diff_tk_nin = tk_nin - old_tk_nin; 481 old_tk_nin = tk_nin; 482 diff_tk_nout = tk_nout - old_tk_nout; 483 old_tk_nout = tk_nout; 484 485 diff_cp_time.cp_user = cp_time.cp_user - old_cp_time.cp_user; 486 diff_cp_time.cp_nice = cp_time.cp_nice - old_cp_time.cp_nice; 487 diff_cp_time.cp_sys = cp_time.cp_sys - old_cp_time.cp_sys; 488 diff_cp_time.cp_intr = cp_time.cp_intr - old_cp_time.cp_intr; 489 diff_cp_time.cp_idle = cp_time.cp_idle - old_cp_time.cp_idle; 490 cp_time_total = diff_cp_time.cp_user + diff_cp_time.cp_nice + 491 diff_cp_time.cp_sys + diff_cp_time.cp_intr + 492 diff_cp_time.cp_idle; 493 old_cp_time = cp_time; 494 495 if (cp_time_total == 0.0) 496 cp_time_total = 1.0; 497 498 if ((dflag == 0) || (Tflag > 0)) 499 printf("%4.0f%5.0f", diff_tk_nin / cp_time_total * 1e6, 500 diff_tk_nout / cp_time_total * 1e6); 501 devstats(hflag); 502 if ((dflag == 0) || (Cflag > 0)) 503 cpustats(); 504 printf("\n"); 505 fflush(stdout); 506 507 if (count >= 0 && --count <= 0) 508 break; 509 510 sleep(waittime); 511 } 512 513 exit(0); 514 } 515 516 static void 517 adddeletion(const char *prefix, int num_selected, 518 char ***deletions, int *num_deletions) 519 { 520 int i; 521 522 for (i = 0; i < num_selected; i++) { 523 char tmpstr[80]; 524 525 if (strcmp(prefix, dev_select[i].device_name) != 0) 526 continue; 527 snprintf(tmpstr, sizeof(tmpstr), "%s%d", 528 dev_select[i].device_name, dev_select[i].unit_number); 529 ++*num_deletions; 530 *deletions = realloc(*deletions, 531 *num_deletions * sizeof(char *)); 532 (*deletions)[*num_deletions - 1] = strdup(tmpstr); 533 } 534 } 535 536 537 static void 538 phdr(__unused int signo) 539 { 540 int i; 541 int printed; 542 543 if ((dflag == 0) || (Tflag > 0)) 544 printf(" tty"); 545 for (i = 0, printed=0;(i < num_devices) && (printed < maxshowdevs);i++){ 546 int di; 547 if (dev_select[i].selected != 0) { 548 di = dev_select[i].position; 549 if (oflag > 0) 550 printf("%12.6s%d ", 551 cur.dinfo->devices[di].device_name, 552 cur.dinfo->devices[di].unit_number); 553 else 554 if (Dflag > 0) 555 printf("%19.6s%d ", 556 cur.dinfo->devices[di].device_name, 557 cur.dinfo->devices[di].unit_number); 558 else 559 printf("%15.6s%d ", 560 cur.dinfo->devices[di].device_name, 561 cur.dinfo->devices[di].unit_number); 562 printed++; 563 } 564 } 565 if ((dflag == 0) || (Cflag > 0)) 566 printf(" cpu\n"); 567 else 568 printf("\n"); 569 570 if ((dflag == 0) || (Tflag > 0)) 571 printf(" tin tout"); 572 573 for (i=0, printed = 0;(i < num_devices) && (printed < maxshowdevs);i++){ 574 if (dev_select[i].selected != 0) { 575 if (oflag > 0) { 576 if (Iflag == 0) 577 printf(" sps tps msps "); 578 else 579 printf(" blk xfr msps "); 580 } else { 581 if (Iflag == 0) { 582 if (Dflag > 0) 583 printf(" KB/t rtps MBr/s wtps MBw/s "); 584 else 585 printf(" KB/t tps MB/s "); 586 } 587 else 588 printf(" KB/t xfrs MB "); 589 } 590 printed++; 591 } 592 } 593 if ((dflag == 0) || (Cflag > 0)) 594 printf(" us ni sy in id\n"); 595 else 596 printf("\n"); 597 598 } 599 600 static void 601 devstats(int perf_select) 602 { 603 int dn; 604 long double kb_per_transfer; 605 long double transfers_per_second; 606 long double transfers_per_secondr, transfers_per_secondw; 607 long double mb_per_second; 608 long double mb_per_secondr, mb_per_secondw; 609 u_int64_t total_bytes, total_transfers, total_blocks; 610 long double busy_seconds; 611 long double total_mb; 612 long double blocks_per_second, ms_per_transaction; 613 614 /* 615 * Calculate elapsed time up front, since it's the same for all 616 * devices. 617 */ 618 busy_seconds = compute_etime(cur.busy_time, last.busy_time); 619 620 for (dn = 0; dn < num_devices; dn++) { 621 int di; 622 623 if (perf_select == 0 && dev_select[dn].selected == 0) 624 continue; 625 626 di = dev_select[dn].position; 627 628 if (compute_stats(&cur.dinfo->devices[di], 629 &last.dinfo->devices[di], busy_seconds, 630 &total_bytes, &total_transfers, 631 &total_blocks, &kb_per_transfer, 632 &transfers_per_second, &mb_per_second, 633 &blocks_per_second, &ms_per_transaction)!= 0) 634 errx(1, "%s", devstat_errbuf); 635 if (compute_stats_read(&cur.dinfo->devices[di], 636 &last.dinfo->devices[di], busy_seconds, 637 NULL, NULL, 638 NULL, NULL, 639 &transfers_per_secondr, &mb_per_secondr, 640 NULL, NULL)!= 0) 641 errx(1, "%s", devstat_errbuf); 642 if (compute_stats_write(&cur.dinfo->devices[di], 643 &last.dinfo->devices[di], busy_seconds, 644 NULL, NULL, 645 NULL, NULL, 646 &transfers_per_secondw, &mb_per_secondw, 647 NULL, NULL)!= 0) 648 errx(1, "%s", devstat_errbuf); 649 650 if (perf_select != 0) { 651 dev_select[dn].bytes = total_bytes; 652 if (dev_select[dn].selected == 0) 653 continue; 654 } 655 656 if (Kflag) { 657 int block_size = cur.dinfo->devices[di].block_size; 658 total_blocks = total_blocks * (block_size ? 659 block_size : 512) / 1024; 660 } 661 662 if (oflag > 0) { 663 int msdig = (ms_per_transaction < 100.0) ? 1 : 0; 664 665 if (Iflag == 0) 666 printf("%4.0Lf%4.0Lf%5.*Lf ", 667 blocks_per_second, 668 transfers_per_second, 669 msdig, 670 ms_per_transaction); 671 else 672 printf("%4.1ju%4.1ju%5.*Lf ", 673 (uintmax_t)total_blocks, 674 (uintmax_t)total_transfers, 675 msdig, 676 ms_per_transaction); 677 } else { 678 if (Iflag == 0) 679 if (Dflag > 0) { 680 printf(" %5.2Lf %4.0Lf %6.2Lf %4.0Lf %6.2Lf ", 681 kb_per_transfer, 682 transfers_per_secondr, 683 mb_per_secondr, 684 transfers_per_secondw, 685 mb_per_secondw); 686 } else { 687 printf(" %5.2Lf %4.0Lf %5.2Lf ", 688 kb_per_transfer, 689 transfers_per_second, 690 mb_per_second); 691 } 692 else { 693 total_mb = total_bytes; 694 total_mb /= 1024 * 1024; 695 696 printf(" %5.2Lf %3.1ju %5.2Lf ", 697 kb_per_transfer, 698 (uintmax_t)total_transfers, 699 total_mb); 700 } 701 } 702 } 703 } 704 705 static void 706 cpustats(void) 707 { 708 if (cp_time_total == 0.0) 709 cp_time_total = 1.0; 710 711 printf(" %2.0f", 100. * diff_cp_time.cp_user / cp_time_total); 712 printf(" %2.0f", 100. * diff_cp_time.cp_nice / cp_time_total); 713 printf(" %2.0f", 100. * diff_cp_time.cp_sys / cp_time_total); 714 printf(" %2.0f", 100. * diff_cp_time.cp_intr / cp_time_total); 715 printf(" %2.0f", 100. * diff_cp_time.cp_idle / cp_time_total); 716 } 717