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