~ubuntu-branches/ubuntu/gutsy/sysstat/gutsy

« back to all changes in this revision

Viewing changes to iostat.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Luberda
  • Date: 2007-03-29 20:47:12 UTC
  • mfrom: (1.1.6 upstream) (2.1.2 etch)
  • Revision ID: james.westby@ubuntu.com-20070329204712-u4eys5pupg7bxp2e
Tags: 7.0.4-4
* Small isag enhacements, backported from version 7.1.3:
  + add support for log subdirectiories and compressed log files,
  + auto load the latest log file,
  + use standard tk_messageBox to display error messages,
  + "save picture" prompts user for choosing path.
* Register FAQ with doc-base.

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
 
50
50
struct comm_stats  comm_stats[2];
51
51
struct io_stats *st_iodev[2];
52
 
struct io_hdr_stats *st_hdr_iodev;
 
52
struct io_nfs_stats *st_ionfs[2];
 
53
struct io_hdr_stats *st_hdr_iodev, *st_hdr_ionfs;
53
54
struct io_dlist *st_dev_list;
54
55
 
55
56
/* Nb of devices and partitions found */
56
57
int iodev_nr = 0;
 
58
/* Nb of NFS mounted directories found */
 
59
int ionfs_nr = 0;
57
60
 
58
61
/* Nb of devices entered on the command line */
59
62
int dlist_idx = 0;
74
77
{
75
78
   fprintf(stderr, _("Usage: %s [ options... ] [ <interval> [ <count> ] ]\n"
76
79
                   "Options are:\n"
77
 
                   "[ -c | -d ] [ -k | -m ] [ -t ] [ -V ] [ -x ]\n"
 
80
                   "[ -c ] [ -d ] [ -n ] [ -k | -m ] [ -t ] [ -V ] [ -x ]\n"
78
81
                   "[ <device> [ ... ] | ALL ] [ -p [ <device> | ALL ] ]\n"),
79
82
           progname);
80
83
   exit(1);
107
110
 
108
111
/*
109
112
 ***************************************************************************
110
 
 * Set every disk_io entry to inactive state
 
113
 * Set every disk_io or nfs_io entry to inactive state
111
114
 ***************************************************************************
112
115
 */
113
 
void set_entries_inactive(int iodev_nr)
 
116
void set_entries_inactive(int ioln_nr, struct io_hdr_stats *st_hdr_ioln)
114
117
{
115
118
   int i;
116
 
   struct io_hdr_stats *shi = st_hdr_iodev;
 
119
   struct io_hdr_stats *shi = st_hdr_ioln;
117
120
 
118
 
   for (i = 0; i < iodev_nr; i++, shi++)
 
121
   for (i = 0; i < ioln_nr; i++, shi++)
119
122
      shi->active = FALSE;
120
123
}
121
124
 
125
128
 * Set structures's state to free for inactive entries
126
129
 ***************************************************************************
127
130
 */
128
 
void free_inactive_entries(int iodev_nr)
 
131
void free_inactive_entries(int ioln_nr, struct io_hdr_stats *st_hdr_ioln)
129
132
{
130
133
   int i;
131
 
   struct io_hdr_stats *shi = st_hdr_iodev;
 
134
   struct io_hdr_stats *shi = st_hdr_ioln;
132
135
 
133
 
   for (i = 0; i < iodev_nr; i++, shi++) {
 
136
   for (i = 0; i < ioln_nr; i++, shi++) {
134
137
      if (!shi->active)
135
138
         shi->used = FALSE;
136
139
   }
164
167
 
165
168
/*
166
169
 ***************************************************************************
 
170
 * Allocate and init I/O NFS directories structures
 
171
 ***************************************************************************
 
172
 */
 
173
void salloc_nfs(int ionfs_nr)
 
174
{
 
175
   int i;
 
176
 
 
177
   for (i = 0; i < 2; i++) {
 
178
      if ((st_ionfs[i] = (struct io_nfs_stats *) malloc(IO_NFS_STATS_SIZE * ionfs_nr)) == NULL) {
 
179
         perror("malloc");
 
180
         exit(4);
 
181
      }
 
182
      memset(st_ionfs[i], 0, IO_NFS_STATS_SIZE * ionfs_nr);
 
183
   }
 
184
 
 
185
   if ((st_hdr_ionfs = (struct io_hdr_stats *) malloc(IO_HDR_STATS_SIZE * ionfs_nr)) == NULL) {
 
186
      perror("malloc");
 
187
      exit(4);
 
188
   }
 
189
   memset(st_hdr_ionfs, 0, IO_HDR_STATS_SIZE * ionfs_nr);
 
190
}
 
191
 
 
192
 
 
193
/*
 
194
 ***************************************************************************
167
195
 * Allocate structures for devices entered on the command line
168
196
 ***************************************************************************
169
197
 */
215
243
   /* Init stat common counters */
216
244
   init_stats();
217
245
 
218
 
   /* How many processors on this machine ? */
 
246
   /* How many processors on this machine? */
219
247
   cpu_nr = get_cpu_nr(~0);
220
248
 
221
249
   /* Get number of block devices and partitions in /proc/diskstats */
256
284
         *flags |= I_F_OLD_KERNEL;
257
285
      }
258
286
   }
259
 
   /* Allocate structures for number of disks found */
 
287
   /*
 
288
    * Allocate structures for number of disks found.
 
289
    * iodev_nr must be <> 0.
 
290
    */
260
291
   salloc_device(iodev_nr);
261
292
 
262
293
   if (HAS_OLD_KERNEL(*flags)) {
270
301
         sprintf(shi->name, "%s%d", K_HDISK, i);
271
302
      }
272
303
   }
 
304
 
 
305
   /* Get number of NFS directories in /proc/self/mountstats */
 
306
   if (DISPLAY_NFS(*flags) &&
 
307
       ((ionfs_nr = get_nfs_mount_nr()) > 0)) {
 
308
      *flags |= I_F_HAS_NFS;
 
309
      ionfs_nr += NR_NFS_PREALLOC;
 
310
 
 
311
      /* Allocate structures for number of NFS directories found */
 
312
      salloc_nfs(ionfs_nr);
 
313
   }
273
314
}
274
315
 
275
316
 
276
317
/*
277
318
 ***************************************************************************
278
 
 * Save stats for current device or partition
 
319
 * Save stats for current device, partition or NFS directory
279
320
 ***************************************************************************
280
321
 */
281
 
void save_dev_stats(char *dev_name, int curr, struct io_stats *sdev)
 
322
void save_stats(char *name, int curr, void *st_io, int ioln_nr,
 
323
                struct io_hdr_stats *st_hdr_ioln)
282
324
{
283
325
   int i;
284
 
   struct io_hdr_stats *st_hdr_iodev_i;
 
326
   struct io_hdr_stats *st_hdr_ioln_i;
285
327
   struct io_stats *st_iodev_i;
 
328
   struct io_nfs_stats *st_ionfs_i;
286
329
 
287
 
   /* Look for device in data table */
288
 
   for (i = 0; i < iodev_nr; i++) {
289
 
      st_hdr_iodev_i = st_hdr_iodev + i;
290
 
      if (!strcmp(st_hdr_iodev_i->name, dev_name)) {
 
330
   /* Look for device or NFS directory in data table */
 
331
   for (i = 0; i < ioln_nr; i++) {
 
332
      st_hdr_ioln_i = st_hdr_ioln + i;
 
333
      if (!strcmp(st_hdr_ioln_i->name, name)) {
291
334
         break;
292
335
      }
293
336
   }
294
337
        
295
 
   if (i == iodev_nr) {
 
338
   if (i == ioln_nr) {
296
339
      /*
297
340
       * This is a new device: look for an unused entry to store it.
298
341
       * Thus we are able to handle dynamically registered devices.
299
342
       */
300
 
      for (i = 0; i < iodev_nr; i++) {
301
 
         st_hdr_iodev_i = st_hdr_iodev + i;
302
 
         if (!st_hdr_iodev_i->used) {
 
343
      for (i = 0; i < ioln_nr; i++) {
 
344
         st_hdr_ioln_i = st_hdr_ioln + i;
 
345
         if (!st_hdr_ioln_i->used) {
303
346
            /* Unused entry found... */
304
 
            st_hdr_iodev_i->used = TRUE;        /* Indicate it is now used */
305
 
            strcpy(st_hdr_iodev_i->name, dev_name);
306
 
            st_iodev_i = st_iodev[!curr] + i;
307
 
            memset(st_iodev_i, 0, IO_STATS_SIZE);
 
347
            st_hdr_ioln_i->used = TRUE; /* Indicate it is now used */
 
348
            strcpy(st_hdr_ioln_i->name, name);
 
349
            if (st_hdr_ioln == st_hdr_iodev) {
 
350
               st_iodev_i = st_iodev[!curr] + i;
 
351
               memset(st_iodev_i, 0, IO_STATS_SIZE);
 
352
            }
 
353
            else {
 
354
               st_ionfs_i = st_ionfs[!curr] + i;
 
355
               memset(st_ionfs_i, 0, IO_NFS_STATS_SIZE);
 
356
            }
308
357
            break;
309
358
         }
310
359
      }
311
360
   }
312
 
   if (i < iodev_nr) {
313
 
      st_hdr_iodev_i = st_hdr_iodev + i;
314
 
      st_hdr_iodev_i->active = TRUE;
315
 
      st_iodev_i = st_iodev[curr] + i;
316
 
      *st_iodev_i = *sdev;
 
361
   if (i < ioln_nr) {
 
362
      st_hdr_ioln_i = st_hdr_ioln + i;
 
363
      st_hdr_ioln_i->active = TRUE;
 
364
      if (st_hdr_ioln == st_hdr_iodev) {
 
365
         st_iodev_i = st_iodev[curr] + i;
 
366
         *st_iodev_i = *((struct io_stats *) st_io);
 
367
      }
 
368
      else {
 
369
         st_ionfs_i = st_ionfs[curr] + i;
 
370
         *st_ionfs_i = *((struct io_nfs_stats *) st_io);
 
371
      }
317
372
   }
318
 
   /* else it was a new device but there was no free structure to store it */
 
373
   /*
 
374
    * else it was a new device or NFS directory
 
375
    * but there was no free structure to store it.
 
376
    */
319
377
}
320
378
 
321
379
 
357
415
          * Read the number of jiffies spent in the different modes,
358
416
          * and compute system uptime in jiffies (1/100ths of a second
359
417
          * if HZ=100).
360
 
          * Some fields are only presnt in 2.6 kernels.
 
418
          * Some fields are only present in 2.6 kernels.
361
419
          */
362
420
         comm_stats[curr].cpu_iowait = 0;       /* For pre 2.6 kernels */
363
421
         comm_stats[curr].cpu_steal = 0;
379
437
          * Compute system uptime in jiffies.
380
438
          * Uptime is multiplied by the number of processors.
381
439
          */
382
 
         comm_stats[curr].uptime = comm_stats[curr].cpu_user   +
 
440
         comm_stats[curr].uptime = comm_stats[curr].cpu_user +
383
441
                                   comm_stats[curr].cpu_nice +
384
442
                                   comm_stats[curr].cpu_system +
385
443
                                   comm_stats[curr].cpu_idle +
390
448
      else if ((!strncmp(line, "cpu0", 4)) && (cpu_nr > 1)) {
391
449
         /*
392
450
          * Read CPU line for proc#0 (if available).
393
 
          * Useful to compute uptime reduced to one processor on SMP machines,
394
 
          * with fewer risks to get an overflow...
 
451
          * This is necessary to compute time interval since
 
452
          * processors may be disabled (offline) sometimes.
 
453
          * (Assume that proc#0 can never be offline).
395
454
          */
396
455
         cc_iowait = cc_hardirq = cc_softirq = cc_steal = 0;
397
456
         sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu",
455
514
         pos = 9;
456
515
 
457
516
         /* Every disk_io entry is potentially unregistered */
458
 
         set_entries_inactive(iodev_nr);
 
517
         set_entries_inactive(iodev_nr, st_hdr_iodev);
459
518
        
460
519
         /* Read disks I/O statistics (for 2.4 kernels) */
461
520
         while (pos < strlen(line) - 1) {
467
526
            sdev.dk_drive      = v_tmp[0];
468
527
            sdev.dk_drive_rblk = v_tmp[1];
469
528
            sdev.dk_drive_wblk = v_tmp[2];
470
 
            save_dev_stats(dev_name, curr, &sdev);
 
529
            save_stats(dev_name, curr, &sdev, iodev_nr, st_hdr_iodev);
471
530
 
472
531
            pos += strcspn(line + pos, " ") + 1;
473
532
         }
474
533
 
475
534
         /* Free structures corresponding to unregistered disks */
476
 
         free_inactive_entries(iodev_nr);
 
535
         free_inactive_entries(iodev_nr, st_hdr_iodev);
477
536
      }
478
537
   }
479
538
 
510
569
                  &sdev.wr_ios, &sdev.wr_sectors) == 4);
511
570
 
512
571
   if (i)
513
 
      save_dev_stats(dev_name, curr, &sdev);
 
572
      save_stats(dev_name, curr, &sdev, iodev_nr, st_hdr_iodev);
514
573
 
515
574
   fclose(fp);
516
575
 
563
622
   struct io_dlist *st_dev_list_i;
564
623
 
565
624
   /* Every I/O device (or partition) is potentially unregistered */
566
 
   set_entries_inactive(iodev_nr);
 
625
   set_entries_inactive(iodev_nr, st_hdr_iodev);
567
626
 
568
627
   for (dev = 0; dev < dlist_idx; dev++) {
569
628
      st_dev_list_i = st_dev_list + dev;
579
638
   }
580
639
 
581
640
   /* Free structures corresponding to unregistered devices */
582
 
   free_inactive_entries(iodev_nr);
 
641
   free_inactive_entries(iodev_nr, st_hdr_iodev);
583
642
}
584
643
 
585
644
 
597
656
   int ok;
598
657
 
599
658
   /* Every I/O device entry is potentially unregistered */
600
 
   set_entries_inactive(iodev_nr);
 
659
   set_entries_inactive(iodev_nr, st_hdr_iodev);
601
660
 
602
661
   /* Open /sys/block directory */
603
662
   if ((dir = opendir(SYSFS_BLOCK)) != NULL) {
624
683
   }
625
684
 
626
685
   /* Free structures corresponding to unregistered devices */
627
 
   free_inactive_entries(iodev_nr);
 
686
   free_inactive_entries(iodev_nr, st_hdr_iodev);
628
687
}
629
688
 
630
689
 
646
705
   unsigned int major, minor;
647
706
 
648
707
   /* Every I/O device entry is potentially unregistered */
649
 
   set_entries_inactive(iodev_nr);
 
708
   set_entries_inactive(iodev_nr, st_hdr_iodev);
650
709
 
651
710
   if ((fp = fopen(DISKSTATS, "r")) == NULL)
652
711
      return;
693
752
             * No match: Use name generated from sysstat.ioconf data (if different
694
753
             * from "nodev") works around known issues with EMC PowerPath.
695
754
             */
696
 
            strcpy(dev_name, ioc_dname);
 
755
            strncpy(dev_name, ioc_dname, MAX_NAME_LEN);
697
756
      }
698
757
 
699
 
      save_dev_stats(dev_name, curr, &sdev);
 
758
      save_stats(dev_name, curr, &sdev, iodev_nr, st_hdr_iodev);
700
759
   }
701
760
 
702
761
   fclose(fp);
703
762
 
704
763
   /* Free structures corresponding to unregistered devices */
705
 
   free_inactive_entries(iodev_nr);
 
764
   free_inactive_entries(iodev_nr, st_hdr_iodev);
706
765
}
707
766
 
708
767
 
723
782
   unsigned int major, minor;
724
783
 
725
784
   /* Every I/O device entry is potentially unregistered */
726
 
   set_entries_inactive(iodev_nr);
 
785
   set_entries_inactive(iodev_nr, st_hdr_iodev);
727
786
 
728
787
   if ((fp = fopen(PPARTITIONS, "r")) == NULL)
729
788
      return;
750
809
      if ((ioc_dname = ioc_name(major, minor)) != NULL) {
751
810
         if (strcmp(dev_name, ioc_dname) && strcmp(ioc_dname, K_NODEV))
752
811
            /* Compensate for EMC PowerPath driver bug */
753
 
            strcpy(dev_name, ioc_dname);
754
 
      }
755
 
 
756
 
      save_dev_stats(dev_name, curr, &sdev);
757
 
   }
758
 
 
759
 
   fclose(fp);
760
 
 
761
 
   /* Free structures corresponding to unregistered devices */
762
 
   free_inactive_entries(iodev_nr);
 
812
            strncpy(dev_name, ioc_dname, MAX_NAME_LEN);
 
813
      }
 
814
 
 
815
      save_stats(dev_name, curr, &sdev, iodev_nr, st_hdr_iodev);
 
816
   }
 
817
 
 
818
   fclose(fp);
 
819
 
 
820
   /* Free structures corresponding to unregistered devices */
 
821
   free_inactive_entries(iodev_nr, st_hdr_iodev);
 
822
}
 
823
 
 
824
/*
 
825
 ***************************************************************************
 
826
 * Read NFS-mount directories stats from /proc/self/mountstats
 
827
 ***************************************************************************
 
828
 */
 
829
void read_nfs_stat(int curr, int flags)
 
830
{
 
831
   FILE *fp;
 
832
   int i, sw = 0;
 
833
   char line[8192];
 
834
   char nfs_name[MAX_NAME_LEN];
 
835
   char mount[10], on[10], bytes[10], aux[32];
 
836
   struct io_nfs_stats snfs;
 
837
 
 
838
   /* Every I/O NFS entry is potentially unregistered */
 
839
   set_entries_inactive(ionfs_nr, st_hdr_ionfs);
 
840
 
 
841
   if ((fp = fopen(NFSMOUNTSTATS, "r")) == NULL)
 
842
      return;
 
843
 
 
844
   sprintf(aux, "%%%ds %%10s %%10s",
 
845
           MAX_NAME_LEN < 200 ? MAX_NAME_LEN : 200);
 
846
 
 
847
   while (fgets(line, 256, fp) != NULL) {
 
848
 
 
849
      /* read NFS directory name */
 
850
      if (!strncmp(line, "device", 6)) {
 
851
         sw = 0;
 
852
         sscanf(line + 6, aux, nfs_name, mount, on);
 
853
         if ((!strncmp(mount, "mounted", 7)) && (!strncmp(on, "on", 2))) {
 
854
            sw = 1;
 
855
         }
 
856
      }
 
857
 
 
858
      sscanf(line, "%10s", bytes);
 
859
      if (sw && (!strncmp(bytes, "bytes:", 6))) {
 
860
         /* Read the stats for the last NFS-mounted directory */
 
861
         i = sscanf(strstr(line, "bytes:") + 6, "%llu %llu %llu %llu %llu %llu",
 
862
                    &snfs.rd_normal_bytes, &snfs.wr_normal_bytes, &snfs.rd_direct_bytes,
 
863
                    &snfs.wr_direct_bytes, &snfs.rd_server_bytes, &snfs.wr_server_bytes);
 
864
 
 
865
         save_stats(nfs_name, curr, &snfs, ionfs_nr, st_hdr_ionfs);
 
866
         sw = 0;
 
867
      }
 
868
   }
 
869
 
 
870
   fclose(fp);
 
871
 
 
872
   /* Free structures corresponding to unregistered devices */
 
873
   free_inactive_entries(ionfs_nr, st_hdr_ionfs);
763
874
}
764
875
 
765
876
 
786
897
 
787
898
/*
788
899
 ***************************************************************************
789
 
 * Display stats header
 
900
 * Display disk stats header
790
901
 ***************************************************************************
791
902
 */
792
 
void write_stat_header(int flags, int *fctr)
 
903
void write_disk_stat_header(int flags, int *fctr)
793
904
{
794
905
   if (DISPLAY_EXTENDED(flags)) {
795
906
      /* Extended stats */
796
 
      printf("Device:         rrqm/s   wrqm/s   r/s   w/s");
 
907
      printf("Device:         rrqm/s   wrqm/s     r/s     w/s");
797
908
      if (DISPLAY_MEGABYTES(flags)) {
798
909
         printf("    rMB/s    wMB/s");
799
910
         *fctr = 2048;
825
936
 
826
937
/*
827
938
 ***************************************************************************
 
939
 * Display NFS stats header
 
940
 ***************************************************************************
 
941
 */
 
942
void write_nfs_stat_header(int flags, int *fctr)
 
943
{
 
944
   printf("Filesystem:           ");
 
945
   if (DISPLAY_KILOBYTES(flags)) {
 
946
      printf("    rkB_nor/s    wkB_nor/s    rkB_dir/s    wkB_dir/s    rkB_svr/s    wkB_svr/s\n");
 
947
      *fctr = 1024;
 
948
   }
 
949
   else if (DISPLAY_MEGABYTES(flags)) {
 
950
      printf("    rMB_nor/s    wMB_nor/s    rMB_dir/s    wMB_dir/s    rMB_svr/s    wMB_svr/s\n");
 
951
      *fctr = 1024 * 1024;
 
952
   }
 
953
   else {
 
954
      printf("   rBlk_nor/s   wBlk_nor/s   rBlk_dir/s   wBlk_dir/s   rBlk_svr/s   wBlk_svr/s\n");
 
955
      *fctr = 512;
 
956
   }
 
957
}
 
958
 
 
959
 
 
960
/*
 
961
 ***************************************************************************
828
962
 * Display extended stats, read from /proc/{diskstats,partitions} or /sys
829
963
 ***************************************************************************
830
964
 */
865
999
 
866
1000
   arqsz = nr_ios ? (rd_sec + wr_sec) / nr_ios : 0.0;
867
1001
 
868
 
   printf("%-13s", shi->name);
869
 
   if (strlen(shi->name) > 10)
870
 
      printf("\n          ");
871
 
   /*       rrq/s wrq/s   r/s   w/s  rsec  wsec  rqsz  qusz await svctm %util */
872
 
   printf(" %8.2f %8.2f %5.2f %5.2f %8.2f %8.2f %8.2f %8.2f %7.2f %6.2f %6.2f\n",
 
1002
   /*      DEV   rrq/s wrq/s   r/s   w/s  rsec  wsec  rqsz  qusz await svctm %util */
 
1003
   printf("%-13s %8.2f %8.2f %7.2f %7.2f %8.2f %8.2f %8.2f %8.2f %7.2f %6.2f %6.2f\n",
 
1004
          shi->name,
873
1005
          S_VALUE(ioj->rd_merges, ioi->rd_merges, itv),
874
1006
          S_VALUE(ioj->wr_merges, ioi->wr_merges, itv),
875
1007
          S_VALUE(ioj->rd_ios, ioi->rd_ios, itv),
899
1031
   unsigned long long rd_sec, wr_sec;
900
1032
 
901
1033
   printf("%-13s", shi->name);
902
 
   if (strlen(shi->name) > 13)
903
 
      printf("\n             ");
904
1034
 
905
1035
   if (HAS_SYSFS(flags) ||
906
1036
       HAS_DISKSTATS(flags) || HAS_PPARTITIONS(flags)) {
933
1063
 
934
1064
/*
935
1065
 ***************************************************************************
 
1066
 * Write NFS stats read from /proc/self/mountstats
 
1067
 ***************************************************************************
 
1068
 */
 
1069
void write_nfs_stat(int curr, unsigned long long itv, int flags, int fctr,
 
1070
                    struct io_hdr_stats *shi, struct io_nfs_stats *ioni,
 
1071
                    struct io_nfs_stats *ionj)
 
1072
{
 
1073
   printf("%-22s %12.2f %12.2f %12.2f %12.2f %12.2f %12.2f\n",
 
1074
          shi->name,
 
1075
          S_VALUE(ionj->rd_normal_bytes, ioni->rd_normal_bytes, itv) / fctr,
 
1076
          S_VALUE(ionj->wr_normal_bytes, ioni->wr_normal_bytes, itv) / fctr,
 
1077
          S_VALUE(ionj->rd_direct_bytes, ioni->rd_direct_bytes, itv) / fctr,
 
1078
          S_VALUE(ionj->wr_direct_bytes, ioni->wr_direct_bytes, itv) / fctr,
 
1079
          S_VALUE(ionj->rd_server_bytes, ioni->rd_server_bytes, itv) / fctr,
 
1080
          S_VALUE(ionj->wr_server_bytes, ioni->wr_server_bytes, itv) / fctr);
 
1081
}
 
1082
 
 
1083
 
 
1084
/*
 
1085
 ***************************************************************************
936
1086
 * Print everything now (stats and uptime)
937
1087
 ***************************************************************************
938
1088
 */
939
 
int write_stat(int curr, int flags, struct tm *loc_time)
 
1089
int write_stat(int curr, int flags, struct tm *rectime)
940
1090
{
941
1091
   int dev, i, fctr = 1;
942
1092
   unsigned long long itv;
943
 
   struct io_hdr_stats *shi = st_hdr_iodev;
944
 
   struct io_stats *ioi, *ioj;
 
1093
   struct io_hdr_stats *shi;
945
1094
   struct io_dlist *st_dev_list_i;
946
1095
 
947
1096
   /*
955
1104
 
956
1105
   /* Print time stamp */
957
1106
   if (DISPLAY_TIMESTAMP(flags)) {
958
 
      strftime(timestamp, sizeof(timestamp), "%X", loc_time);
 
1107
      strftime(timestamp, sizeof(timestamp), "%X", rectime);
959
1108
      printf(_("Time: %s\n"), timestamp);
960
1109
   }
961
1110
 
963
1112
    * itv is multiplied by the number of processors.
964
1113
    * This is OK to compute CPU usage since the number of jiffies spent in the
965
1114
    * different modes (user, nice, etc.) is the sum of all the processors.
966
 
    * But itv should be reduced to one processor before displaying disk
 
1115
    * But itv should be reduced to one processor before displaying disk or NFS
967
1116
    * utilization.
968
1117
    */
969
1118
   if (!comm_stats[!curr].uptime)
980
1129
   if (!itv)
981
1130
      itv = 1;
982
1131
 
983
 
   if (!DISPLAY_DISK_ONLY(flags))
 
1132
   if (DISPLAY_CPU(flags))
984
1133
      /* Display CPU utilization */
985
1134
      write_cpu_stat(curr, itv);
986
1135
 
995
1144
         itv = 1;
996
1145
   }
997
1146
 
998
 
   if (!DISPLAY_CPU_ONLY(flags)) {
999
 
 
1000
 
      /* Display stats header */
1001
 
      write_stat_header(flags, &fctr);
 
1147
   if (DISPLAY_DISK(flags)) {
 
1148
      struct io_stats *ioi, *ioj;
 
1149
 
 
1150
      shi = st_hdr_iodev;
 
1151
 
 
1152
      /* Display disk stats header */
 
1153
      write_disk_stat_header(flags, &fctr);
1002
1154
 
1003
1155
      if (DISPLAY_EXTENDED(flags) &&
1004
1156
          (HAS_OLD_KERNEL(flags) || HAS_PLAIN_KERNEL24(flags))) {
1050
1202
      }
1051
1203
      printf("\n");
1052
1204
   }
 
1205
 
 
1206
   if (DISPLAY_NFS(flags)) {
 
1207
      struct io_nfs_stats *ioni, *ionj;
 
1208
 
 
1209
      shi = st_hdr_ionfs;
 
1210
 
 
1211
      /* Display NFS stats header */
 
1212
      write_nfs_stat_header(flags, &fctr);
 
1213
 
 
1214
      if (!HAS_NFS(flags)) {
 
1215
         /* No NFS stats */
 
1216
         printf("\n");
 
1217
         return 1;
 
1218
      }
 
1219
 
 
1220
      for (i = 0; i < ionfs_nr; i++, shi++) {
 
1221
         if (shi->used) {
 
1222
        
 
1223
            ioni = st_ionfs[curr] + i;
 
1224
            ionj = st_ionfs[!curr] + i;
 
1225
            write_nfs_stat(curr, itv, flags, fctr, shi, ioni, ionj);
 
1226
         }
 
1227
      }
 
1228
      printf("\n");
 
1229
   }
1053
1230
   return 1;
1054
1231
}
1055
1232
 
1060
1237
 * and display them.
1061
1238
 ***************************************************************************
1062
1239
 */
1063
 
void rw_io_stat_loop(int flags, long int count, struct tm *loc_time)
 
1240
void rw_io_stat_loop(int flags, long int count, struct tm *rectime)
1064
1241
{
1065
1242
   int curr = 1;
1066
1243
   int next;
1094
1271
            read_ppartitions_stat(curr, flags);
1095
1272
      }
1096
1273
 
 
1274
      /* Read NFS directories stats */
 
1275
      if (HAS_NFS(flags))
 
1276
         read_nfs_stat(curr, flags);
 
1277
 
1097
1278
      /* Save time */
1098
 
      get_localtime(loc_time);
 
1279
      get_localtime(rectime);
1099
1280
 
1100
1281
      /* Print results */
1101
 
      if ((next = write_stat(curr, flags, loc_time))
 
1282
      if ((next = write_stat(curr, flags, rectime))
1102
1283
          && (count > 0))
1103
1284
         count--;
1104
1285
      fflush(stdout);
1127
1308
   long count = 1;
1128
1309
   struct utsname header;
1129
1310
   struct io_dlist *st_dev_list_i;
1130
 
   struct tm loc_time;
 
1311
   struct tm rectime;
1131
1312
 
1132
1313
#ifdef USE_NLS
1133
1314
   /* Init National Language Support */
1170
1351
            switch (*(argv[opt] + i)) {
1171
1352
 
1172
1353
             case 'c':
1173
 
               flags |= I_D_CPU_ONLY;   /* Display cpu usage only */
1174
 
               flags &= ~I_D_DISK_ONLY;
 
1354
               flags |= I_D_CPU;        /* Display cpu usage */
1175
1355
               break;
1176
1356
 
1177
1357
             case 'd':
1178
 
               flags |= I_D_DISK_ONLY;  /* Display disk utilization only */
1179
 
               flags &= ~I_D_CPU_ONLY;
 
1358
               flags |= I_D_DISK;       /* Display disk utilization */
1180
1359
               break;
1181
1360
        
1182
1361
             case 'k':
1190
1369
                  usage(argv[0]);
1191
1370
               flags |= I_D_MEGABYTES;  /* Display stats in MB/s */
1192
1371
               break;
 
1372
        
 
1373
             case 'n':
 
1374
               flags |= I_D_NFS;        /* Display NFS stats */
 
1375
               break;
1193
1376
 
1194
1377
             case 't':
1195
1378
               flags |= I_D_TIMESTAMP;  /* Display timestamp */
1234
1417
      }
1235
1418
   }
1236
1419
 
1237
 
   /* Linux does not provide extended stats for partitions */
 
1420
   /* Default: Display CPU and DISK reports */
 
1421
   if (!DISPLAY_CPU(flags) && !DISPLAY_DISK(flags) && !DISPLAY_NFS(flags))
 
1422
      flags |= I_D_CPU + I_D_DISK;
 
1423
   /*
 
1424
    * Also display DISK reports if options -p, -x or a device has been entered
 
1425
    * on the command line.
 
1426
    */
 
1427
   if (DISPLAY_PARTITIONS(flags) || DISPLAY_EXTENDED(flags) ||
 
1428
       DISPLAY_UNFILTERED(flags))
 
1429
      flags |= I_D_DISK;
 
1430
 
 
1431
   /* Linux does not provide extended stats for partitions nor for NFS directories */
1238
1432
   if (DISPLAY_PARTITIONS(flags) && DISPLAY_EXTENDED(flags)) {
1239
1433
      fprintf(stderr, _("-x and -p options are mutually exclusive\n"));
1240
1434
      exit(1);
1247
1441
   /* Init structures according to machine architecture */
1248
1442
   io_sys_init(&flags);
1249
1443
 
1250
 
   get_localtime(&loc_time);
 
1444
   get_localtime(&rectime);
1251
1445
 
1252
1446
   /* Get system name, release number and hostname */
1253
1447
   uname(&header);
1254
 
   print_gal_header(&loc_time,
 
1448
   print_gal_header(&rectime,
1255
1449
                    header.sysname, header.release, header.nodename);
1256
1450
   printf("\n");
1257
1451
 
1259
1453
   alarm_handler(0);
1260
1454
 
1261
1455
   /* Main loop */
1262
 
   rw_io_stat_loop(flags, count, &loc_time);
 
1456
   rw_io_stat_loop(flags, count, &rectime);
1263
1457
 
1264
1458
   return 0;
1265
1459
}