Correct BSD License clause numbering from 1-2-4 to 1-2-3.
[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. 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
103 #include <err.h>
104 #include <ctype.h>
105 #include <fcntl.h>
106 #include <kinfo.h>
107 #include <stdio.h>
108 #include <stdlib.h>
109 #include <string.h>
110 #include <unistd.h>
111 #include <limits.h>
112 #include <devstat.h>
113
114 struct statinfo cur, last;
115 uint64_t tk_nin, old_tk_nin, diff_tk_nin;
116 uint64_t tk_nout, old_tk_nout, diff_tk_nout;
117 struct kinfo_cputime cp_time, old_cp_time, diff_cp_time;
118 double cp_time_total;
119 int num_devices;
120 struct device_selection *dev_select;
121 int maxshowdevs;
122 int dflag = 0, Dflag=0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0;
123
124 /* local function declarations */
125 static void usage(void);
126 static void phdr(int signo);
127 static void devstats(int perf_select);
128 static void cpustats(void);
129
130 static void
131 usage(void)
132 {
133         /*
134          * We also support the following 'traditional' syntax:
135          * iostat [drives] [wait [count]]
136          * This isn't mentioned in the man page, or the usage statement,
137          * but it is supported.
138          */
139         fprintf(stderr, "usage: iostat [-CdhIKoT] [-c count]"
140                 " [-n devs]\n"
141                 "\t      [-t type,if,pass] [-w wait] [drives]\n");
142 }
143
144 int
145 main(int argc, char **argv)
146 {
147         int c;
148         int tflag = 0, hflag = 0, cflag = 0, wflag = 0, nflag = 0;
149         int count = 0, waittime = 0;
150         struct devstat_match *matches;
151         int num_matches = 0;
152         int hz;
153         int headercount;
154         long generation;
155         int num_devices_specified;
156         int num_selected, num_selections;
157         long select_generation;
158         char **specified_devices;
159         devstat_select_mode select_mode;
160
161         matches = NULL;
162         maxshowdevs = 3;
163
164         while ((c = getopt(argc, argv, "c:CdDhIKM:n:N:ot:Tw:")) != -1) {
165                 switch(c) {
166                         case 'c':
167                                 cflag++;
168                                 count = atoi(optarg);
169                                 if (count < 1)
170                                         errx(1, "count %d is < 1", count);
171                                 break;
172                         case 'C':
173                                 Cflag++;
174                                 break;
175                         case 'd':
176                                 dflag++;
177                                 break;
178                         case 'D':
179                                 Dflag++;
180                                 break;
181                         case 'h':
182                                 hflag++;
183                                 break;
184                         case 'I':
185                                 Iflag++;
186                                 break;
187                         case 'K':
188                                 Kflag++;
189                                 break;
190                         case 'n':
191                                 nflag++;
192                                 maxshowdevs = atoi(optarg);
193                                 if (maxshowdevs < 0)
194                                         errx(1, "number of devices %d is < 0",
195                                              maxshowdevs);
196                                 break;
197                         case 'o':
198                                 oflag++;
199                                 break;
200                         case 't':
201                                 tflag++;
202                                 if (buildmatch(optarg, &matches, 
203                                                &num_matches) != 0)
204                                         errx(1, "%s", devstat_errbuf);
205                                 break;
206                         case 'T':
207                                 Tflag++;
208                                 break;
209                         case 'w':
210                                 wflag++;
211                                 waittime = atoi(optarg);
212                                 if (waittime < 1)
213                                         errx(1, "wait time is < 1");
214                                 break;
215                         default:
216                                 usage();
217                                 exit(1);
218                                 break;
219                 }
220         }
221
222         argc -= optind;
223         argv += optind;
224
225         /*
226          * Make sure that the userland devstat version matches the kernel
227          * devstat version.  If not, exit and print a message informing 
228          * the user of his mistake.
229          */
230         if (checkversion() < 0)
231                 errx(1, "%s", devstat_errbuf);
232
233         /*
234          * Figure out how many devices we should display.
235          */
236         if (nflag == 0) {
237                 if (oflag > 0) {
238                         if ((dflag > 0) && (Cflag == 0) && (Tflag == 0))
239                                 maxshowdevs = 5;
240                         else if ((dflag > 0) && (Tflag > 0) && (Cflag == 0))
241                                 maxshowdevs = 5;
242                         else
243                                 maxshowdevs = 4;
244                 } else {
245                         if ((dflag > 0) && (Cflag == 0))
246                                 maxshowdevs = 4;                
247                         else
248                                 maxshowdevs = 3;
249                 }
250         }
251
252         /* find out how many devices we have */
253         if ((num_devices = getnumdevs()) < 0)
254                 err(1, "can't get number of devices");
255
256         if ((cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo))) ==
257              NULL)
258                 err(1, "devinfo malloc failed");
259         if ((last.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo))) ==
260              NULL)
261                 err(1, "devinfo malloc failed");
262         bzero(cur.dinfo, sizeof(struct devinfo));
263         bzero(last.dinfo, sizeof(struct devinfo));
264
265         /*
266          * Grab all the devices.  We don't look to see if the list has
267          * changed here, since it almost certainly has.  We only look for
268          * errors.
269          */
270         if (getdevs(&cur) == -1)
271                 errx(1, "%s", devstat_errbuf);
272
273         num_devices = cur.dinfo->numdevs;
274         generation = cur.dinfo->generation;
275
276         /*
277          * If the user specified any devices on the command line, see if
278          * they are in the list of devices we have now.
279          */
280         if ((specified_devices = (char **)malloc(sizeof(char *))) == NULL)
281                 err(1, "specified_devices malloc failed");
282         for (num_devices_specified = 0; *argv; ++argv) {
283                 if (isdigit(**argv))
284                         break;
285                 num_devices_specified++;
286                 specified_devices = (char **)realloc(specified_devices,
287                                                      sizeof(char *) *
288                                                      num_devices_specified);
289                 specified_devices[num_devices_specified - 1] = *argv;
290
291         }
292         if (nflag == 0 && maxshowdevs < num_devices_specified)
293                 maxshowdevs = num_devices_specified;
294
295         dev_select = NULL;
296
297         if ((num_devices_specified == 0) && (num_matches == 0))
298                 select_mode = DS_SELECT_ADD;
299         else
300                 select_mode = DS_SELECT_ONLY;
301
302         /*
303          * At this point, selectdevs will almost surely indicate that the
304          * device list has changed, so we don't look for return values of 0
305          * or 1.  If we get back -1, though, there is an error.
306          */
307         if (selectdevs(&dev_select, &num_selected,
308                        &num_selections, &select_generation,
309                        generation, cur.dinfo->devices, num_devices,
310                        matches, num_matches,
311                        specified_devices, num_devices_specified,
312                        select_mode, maxshowdevs, hflag) == -1)
313                 errx(1, "%s", devstat_errbuf);
314
315         /*
316          * Look for the traditional wait time and count arguments.
317          */
318         if (*argv) {
319                 waittime = atoi(*argv);
320
321                 /* Let the user know he goofed, but keep going anyway */
322                 if (wflag != 0) 
323                         warnx("discarding previous wait interval, using"
324                               " %d instead", waittime);
325                 wflag++;
326
327                 if (*++argv) {
328                         count = atoi(*argv);
329                         if (cflag != 0)
330                                 warnx("discarding previous count, using %d"
331                                       " instead", count);
332                         cflag++;
333                 } else
334                         count = -1;
335         }
336
337         /*
338          * If the user specified a count, but not an interval, we default
339          * to an interval of 1 second.
340          */
341         if ((wflag == 0) && (cflag > 0))
342                 waittime = 1;
343
344         /*
345          * If the user specified a wait time, but not a count, we want to
346          * go on ad infinitum.  This can be redundant if the user uses the
347          * traditional method of specifying the wait, since in that case we
348          * already set count = -1 above.  Oh well.
349          */
350         if ((wflag > 0) && (cflag == 0))
351                 count = -1;
352
353         if (kinfo_get_sched_hz(&hz))
354                 err(1, "kinfo_get_sched_hz");
355         if (kinfo_get_sched_stathz(&hz))
356                 err(1, "kinfo_get_sched_stathz");
357
358         /*
359          * If the user stops the program (control-Z) and then resumes it,
360          * print out the header again.
361          */
362         signal(SIGCONT, phdr);
363
364         for (headercount = 1;;) {
365                 struct devinfo *tmp_dinfo;
366
367                 if (!--headercount) {
368                         phdr(0);
369                         headercount = 20;
370                 }
371                 if (kinfo_get_tty_tk_nin(&tk_nin))
372                         err(1, "kinfo_get_tty_tk_nin");
373                 if (kinfo_get_tty_tk_nout(&tk_nout))
374                         err(1, "kinfo_get_tty_tk_nout");
375                 if (kinfo_get_sched_cputime(&cp_time))
376                         err(1, "kinfo_get_sched_cputime");
377
378                 tmp_dinfo = last.dinfo;
379                 last.dinfo = cur.dinfo;
380                 cur.dinfo = tmp_dinfo;
381
382                 last.busy_time = cur.busy_time;
383
384                 /*
385                  * Here what we want to do is refresh our device stats.
386                  * getdevs() returns 1 when the device list has changed.
387                  * If the device list has changed, we want to go through
388                  * the selection process again, in case a device that we
389                  * were previously displaying has gone away.
390                  */
391                 switch (getdevs(&cur)) {
392                 case -1:
393                         errx(1, "%s", devstat_errbuf);
394                         break;
395                 case 1: {
396                         int retval;
397
398                         num_devices = cur.dinfo->numdevs;
399                         generation = cur.dinfo->generation;
400                         retval = selectdevs(&dev_select, &num_selected,
401                                             &num_selections, &select_generation,
402                                             generation, cur.dinfo->devices,
403                                             num_devices, matches, num_matches,
404                                             specified_devices,
405                                             num_devices_specified,
406                                             select_mode, maxshowdevs, hflag);
407                         switch(retval) {
408                         case -1:
409                                 errx(1, "%s", devstat_errbuf);
410                                 break;
411                         case 1:
412                                 phdr(0);
413                                 headercount = 20;
414                                 break;
415                         default:
416                                 break;
417                         }
418                         break;
419                 }
420                 default:
421                         break;
422                 }
423
424                 /*
425                  * We only want to re-select devices if we're in 'top'
426                  * mode.  This is the only mode where the devices selected
427                  * could actually change.
428                  */
429                 if (hflag > 0) {
430                         int retval;
431                         retval = selectdevs(&dev_select, &num_selected,
432                                             &num_selections, &select_generation,
433                                             generation, cur.dinfo->devices,
434                                             num_devices, matches, num_matches,
435                                             specified_devices,
436                                             num_devices_specified,
437                                             select_mode, maxshowdevs, hflag);
438                         switch(retval) {
439                         case -1:
440                                 errx(1,"%s", devstat_errbuf);
441                                 break;
442                         case 1:
443                                 phdr(0);
444                                 headercount = 20;
445                                 break;
446                         default:
447                                 break;
448                         }
449                 }
450
451                 diff_tk_nin = tk_nin - old_tk_nin;
452                 old_tk_nin = tk_nin;
453                 diff_tk_nout = tk_nout - old_tk_nout;
454                 old_tk_nout = tk_nout;
455
456                 diff_cp_time.cp_user = cp_time.cp_user - old_cp_time.cp_user;
457                 diff_cp_time.cp_nice = cp_time.cp_nice - old_cp_time.cp_nice;
458                 diff_cp_time.cp_sys = cp_time.cp_sys - old_cp_time.cp_sys;
459                 diff_cp_time.cp_intr = cp_time.cp_intr - old_cp_time.cp_intr;
460                 diff_cp_time.cp_idle = cp_time.cp_idle - old_cp_time.cp_idle;
461                 cp_time_total = diff_cp_time.cp_user + diff_cp_time.cp_nice +
462                     diff_cp_time.cp_sys + diff_cp_time.cp_intr +
463                     diff_cp_time.cp_idle;
464                 old_cp_time = cp_time;
465
466                 if (cp_time_total == 0.0)
467                         cp_time_total = 1.0;
468
469                 if ((dflag == 0) || (Tflag > 0))
470                         printf("%4.0f%5.0f", diff_tk_nin / cp_time_total * 1e6, 
471                                 diff_tk_nout / cp_time_total * 1e6);
472                 devstats(hflag);
473                 if ((dflag == 0) || (Cflag > 0))
474                         cpustats();
475                 printf("\n");
476                 fflush(stdout);
477
478                 if (count >= 0 && --count <= 0)
479                         break;
480
481                 sleep(waittime);
482         }
483
484         exit(0);
485 }
486
487 static void
488 phdr(__unused int signo)
489 {
490         int i;
491         int printed;
492
493         if ((dflag == 0) || (Tflag > 0))
494                 printf("      tty");
495         for (i = 0, printed=0;(i < num_devices) && (printed < maxshowdevs);i++){
496                 int di;
497                 if ((dev_select[i].selected != 0)
498                  && (dev_select[i].selected <= maxshowdevs)) {
499                         di = dev_select[i].position;
500                         if (oflag > 0)
501                                 printf("%12.6s%d ", 
502                                             cur.dinfo->devices[di].device_name,
503                                             cur.dinfo->devices[di].unit_number);
504                         else
505                                 if (Dflag > 0)
506                                         printf("%19.6s%d            ",
507                                                     cur.dinfo->devices[di].device_name,
508                                                     cur.dinfo->devices[di].unit_number);
509                                 else
510                                         printf("%15.6s%d ",
511                                                     cur.dinfo->devices[di].device_name,
512                                                     cur.dinfo->devices[di].unit_number);
513                         printed++;
514                 }
515         }
516         if ((dflag == 0) || (Cflag > 0))
517                 printf("            cpu\n");
518         else
519                 printf("\n");
520
521         if ((dflag == 0) || (Tflag > 0))
522                 printf(" tin tout");
523
524         for (i=0, printed = 0;(i < num_devices) && (printed < maxshowdevs);i++){
525                 if ((dev_select[i].selected != 0)
526                  && (dev_select[i].selected <= maxshowdevs)) {
527                         if (oflag > 0) {
528                                 if (Iflag == 0)
529                                         printf(" sps tps  msps ");
530                                 else
531                                         printf(" blk xfr msps ");
532                         } else {
533                                 if (Iflag == 0) {
534                                         if (Dflag > 0)
535                                                 printf("   KB/t rtps  MBr/s wtps  MBw/s ");
536                                         else
537                                                 printf("  KB/t tps   MB/s ");
538                                 }
539                                 else
540                                         printf("  KB/t xfrs   MB ");
541                         }
542                         printed++;
543                 }
544         }
545         if ((dflag == 0) || (Cflag > 0))
546                 printf(" us ni sy in id\n");
547         else
548                 printf("\n");
549
550 }
551
552 static void
553 devstats(int perf_select)
554 {
555         int dn;
556         long double kb_per_transfer;
557         long double transfers_per_second;
558         long double transfers_per_secondr, transfers_per_secondw;
559         long double mb_per_second;
560         long double mb_per_secondr, mb_per_secondw;
561         u_int64_t total_bytes, total_transfers, total_blocks;
562         long double busy_seconds;
563         long double total_mb;
564         long double blocks_per_second, ms_per_transaction;
565         
566         /*
567          * Calculate elapsed time up front, since it's the same for all
568          * devices.
569          */
570         busy_seconds = compute_etime(cur.busy_time, last.busy_time);
571
572         for (dn = 0; dn < num_devices; dn++) {
573                 int di;
574
575                 if (((perf_select == 0) && (dev_select[dn].selected == 0))
576                  || (dev_select[dn].selected > maxshowdevs))
577                         continue;
578
579                 di = dev_select[dn].position;
580
581                 if (compute_stats(&cur.dinfo->devices[di],
582                                   &last.dinfo->devices[di], busy_seconds,
583                                   &total_bytes, &total_transfers,
584                                   &total_blocks, &kb_per_transfer,
585                                   &transfers_per_second, &mb_per_second,
586                                   &blocks_per_second, &ms_per_transaction)!= 0)
587                         errx(1, "%s", devstat_errbuf);
588                 if (compute_stats_read(&cur.dinfo->devices[di],
589                                 &last.dinfo->devices[di], busy_seconds,
590                                 NULL, NULL,
591                                 NULL, NULL,
592                                 &transfers_per_secondr, &mb_per_secondr,
593                                 NULL, NULL)!= 0)
594                         errx(1, "%s", devstat_errbuf);
595                 if (compute_stats_write(&cur.dinfo->devices[di],
596                                 &last.dinfo->devices[di], busy_seconds,
597                                 NULL, NULL,
598                                 NULL, NULL,
599                                 &transfers_per_secondw, &mb_per_secondw,
600                                 NULL, NULL)!= 0)
601                         errx(1, "%s", devstat_errbuf);
602
603                 if (perf_select != 0) {
604                         dev_select[dn].bytes = total_bytes;
605                         if ((dev_select[dn].selected == 0)
606                          || (dev_select[dn].selected > maxshowdevs))
607                                 continue;
608                 }
609
610                 if (Kflag) {
611                         int block_size = cur.dinfo->devices[di].block_size;
612                         total_blocks = total_blocks * (block_size ?
613                                                        block_size : 512) / 1024;
614                 }
615
616                 if (oflag > 0) {
617                         int msdig = (ms_per_transaction < 100.0) ? 1 : 0;
618
619                         if (Iflag == 0)
620                                 printf("%4.0Lf%4.0Lf%5.*Lf ",
621                                        blocks_per_second,
622                                        transfers_per_second,
623                                        msdig,
624                                        ms_per_transaction);
625                         else 
626                                 printf("%4.1ju%4.1ju%5.*Lf ",
627                                        (uintmax_t)total_blocks,
628                                        (uintmax_t)total_transfers,
629                                        msdig,
630                                        ms_per_transaction);
631                 } else {
632                         if (Iflag == 0) 
633                                 if (Dflag > 0) {
634                                         printf(" %5.2Lf %4.0Lf %6.2Lf %4.0Lf %6.2Lf  ",
635                                                kb_per_transfer,
636                                                transfers_per_secondr,
637                                                mb_per_secondr,
638                                                transfers_per_secondw,
639                                                mb_per_secondw);
640                                 } else {
641                                         printf(" %5.2Lf %4.0Lf %5.2Lf ",
642                                                kb_per_transfer,
643                                                transfers_per_second,
644                                                mb_per_second);
645                                 }
646                         else {
647                                 total_mb = total_bytes;
648                                 total_mb /= 1024 * 1024;
649
650                                 printf(" %5.2Lf %3.1ju %5.2Lf ",
651                                        kb_per_transfer,
652                                        (uintmax_t)total_transfers,
653                                        total_mb);
654                         }
655                 }
656         }
657 }
658
659 static void
660 cpustats(void)
661 {
662         if (cp_time_total == 0.0)
663                 cp_time_total = 1.0;
664
665         printf(" %2.0f", 100. * diff_cp_time.cp_user / cp_time_total);
666         printf(" %2.0f", 100. * diff_cp_time.cp_nice / cp_time_total);
667         printf(" %2.0f", 100. * diff_cp_time.cp_sys / cp_time_total);
668         printf(" %2.0f", 100. * diff_cp_time.cp_intr / cp_time_total);
669         printf(" %2.0f", 100. * diff_cp_time.cp_idle / cp_time_total);
670 }