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