~ubuntu-branches/ubuntu/jaunty/sysstat/jaunty

« back to all changes in this revision

Viewing changes to iostat.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Luberda
  • Date: 2007-05-03 11:05:07 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20070503110507-myx4tgq3em3dndbb
Tags: 7.1.4-1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * iostat: report CPU and I/O statistics
3
 
 * (C) 1998-2006 by Sebastien GODARD (sysstat <at> wanadoo.fr)
 
3
 * (C) 1998-2007 by Sebastien GODARD (sysstat <at> wanadoo.fr)
4
4
 *
5
5
 ***************************************************************************
6
6
 * This program is free software; you can redistribute it and/or modify it *
37
37
#include "common.h"
38
38
#include "ioconf.h"
39
39
 
40
 
 
41
40
#ifdef USE_NLS
42
41
#include <locale.h>
43
42
#include <libintl.h>
53
52
struct io_hdr_stats *st_hdr_iodev, *st_hdr_ionfs;
54
53
struct io_dlist *st_dev_list;
55
54
 
56
 
/* Nb of devices and partitions found */
57
 
int iodev_nr = 0;
58
 
/* Nb of NFS mounted directories found */
59
 
int ionfs_nr = 0;
60
55
 
61
 
/* Nb of devices entered on the command line */
62
 
int dlist_idx = 0;
 
56
int iodev_nr = 0;       /* Nb of devices and partitions found */
 
57
int ionfs_nr = 0;       /* Nb of NFS mounted directories found */
 
58
int cpu_nr = 0;         /* Nb of processors on the machine */
 
59
int dlist_idx = 0;      /* Nb of devices entered on the command line */
63
60
 
64
61
long interval = 0;
65
 
unsigned char timestamp[64];
66
 
 
67
 
/* Nb of processors on the machine */
68
 
int cpu_nr = 0;
 
62
char timestamp[64];
69
63
 
70
64
 
71
65
/*
77
71
{
78
72
   fprintf(stderr, _("Usage: %s [ options... ] [ <interval> [ <count> ] ]\n"
79
73
                   "Options are:\n"
80
 
                   "[ -c ] [ -d ] [ -n ] [ -k | -m ] [ -t ] [ -V ] [ -x ]\n"
 
74
                   "[ -c ] [ -d ] [ -N ] [ -n ] [ -k | -m ] [ -t ] [ -V ] [ -x ]\n"
81
75
                   "[ <device> [ ... ] | ALL ] [ -p [ <device> | ALL ] ]\n"),
82
76
           progname);
83
77
   exit(1);
222
216
   }
223
217
 
224
218
   if (i == *dlist_idx) {
225
 
      /* Device not found: store it */
 
219
      /* Device not found: Store it */
226
220
      (*dlist_idx)++;
227
221
      strncpy(sdli->dev_name, device_name, MAX_NAME_LEN - 1);
228
222
   }
395
389
   unsigned long long cc_idle, cc_iowait, cc_steal;
396
390
   unsigned long long cc_user, cc_nice, cc_system, cc_hardirq, cc_softirq;
397
391
 
398
 
 
399
392
   /*
400
393
    * Prepare pointers on the 4 disk structures in case we have a
401
394
    * /proc/stat file with "disk_rblk", etc. entries.
445
438
                                   comm_stats[curr].cpu_steal;
446
439
      }
447
440
 
448
 
      else if ((!strncmp(line, "cpu0", 4)) && (cpu_nr > 1)) {
 
441
      else if ((!strncmp(line, "cpu0", 4)) && !comm_stats[curr].uptime0
 
442
               && (cpu_nr > 1)) {
449
443
         /*
450
444
          * Read CPU line for proc#0 (if available).
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).
 
445
          * Done only if /proc/uptime was unavailable.
454
446
          */
455
447
         cc_iowait = cc_hardirq = cc_softirq = cc_steal = 0;
456
448
         sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu",
696
688
{
697
689
   FILE *fp;
698
690
   char line[256], dev_name[MAX_NAME_LEN];
 
691
   char *dm_name;
699
692
   struct io_stats sdev;
700
693
   int i;
701
694
   unsigned long rd_ios, rd_merges_or_rd_sec, rd_ticks_or_wr_sec, wr_ios;
743
736
         sdev.wr_sectors = rd_ticks_or_wr_sec;
744
737
      }
745
738
      else
746
 
         /* Unknown entry: ignore it */
 
739
         /* Unknown entry: Ignore it */
747
740
         continue;
748
741
 
749
742
      if ((ioc_dname = ioc_name(major, minor)) != NULL) {
755
748
            strncpy(dev_name, ioc_dname, MAX_NAME_LEN);
756
749
      }
757
750
 
 
751
      if ((DISPLAY_DEVMAP_NAME(flags)) && (major == DEVMAP_MAJOR)) {
 
752
         /*
 
753
          * If the device is a device mapper device, try to get its
 
754
          * assigned name of its logical device.
 
755
          */
 
756
         dm_name = transform_devmapname(major, minor);
 
757
         if (dm_name)
 
758
            strcpy(dev_name, dm_name);
 
759
      }
 
760
 
758
761
      save_stats(dev_name, curr, &sdev, iodev_nr, st_hdr_iodev);
759
762
   }
760
 
 
761
763
   fclose(fp);
762
764
 
763
765
   /* Free structures corresponding to unregistered devices */
778
780
   unsigned long rd_ios, rd_merges, rd_ticks, wr_ios, wr_merges, wr_ticks;
779
781
   unsigned long ios_pgr, tot_ticks, rq_ticks;
780
782
   unsigned long long rd_sec, wr_sec;
781
 
   char *ioc_dname;
 
783
   char *ioc_dname, *dm_name;
782
784
   unsigned int major, minor;
783
785
 
784
786
   /* Every I/O device entry is potentially unregistered */
803
805
         sdev.rq_ticks   = rq_ticks;
804
806
      }
805
807
      else
806
 
         /* Unknown entry: ignore it */
 
808
         /* Unknown entry: Ignore it */
807
809
         continue;
808
810
 
809
811
      if ((ioc_dname = ioc_name(major, minor)) != NULL) {
812
814
            strncpy(dev_name, ioc_dname, MAX_NAME_LEN);
813
815
      }
814
816
 
 
817
      if ((DISPLAY_DEVMAP_NAME(flags)) && (major == DEVMAP_MAJOR)) {
 
818
         /* Get device mapper logical name */
 
819
         dm_name = transform_devmapname(major, minor);
 
820
         if (dm_name)
 
821
            strcpy(dev_name, dm_name);
 
822
      }
 
823
 
815
824
      save_stats(dev_name, curr, &sdev, iodev_nr, st_hdr_iodev);
816
825
   }
817
 
 
818
826
   fclose(fp);
819
827
 
820
828
   /* Free structures corresponding to unregistered devices */
983
991
   util = S_VALUE(ioj->tot_ticks, ioi->tot_ticks, itv);
984
992
   svctm = tput ? util / tput : 0.0;
985
993
   /*
986
 
    * kernel gives ticks already in milliseconds for all platforms
 
994
    * Kernel gives ticks already in milliseconds for all platforms
987
995
    * => no need for further scaling.
988
996
    */
989
997
   await = nr_ios ?
1013
1021
          await,
1014
1022
          /* The ticks output is biased to output 1000 ticks per second */
1015
1023
          svctm,
1016
 
          /* Again: ticks in milliseconds */
 
1024
          /* Again: Ticks in milliseconds */
1017
1025
          util / 10.0);
1018
1026
}
1019
1027
 
1086
1094
 * Print everything now (stats and uptime)
1087
1095
 ***************************************************************************
1088
1096
 */
1089
 
int write_stat(int curr, int flags, struct tm *rectime)
 
1097
int write_stats(int curr, int flags, struct tm *rectime)
1090
1098
{
1091
1099
   int dev, i, fctr = 1;
1092
1100
   unsigned long long itv;
1093
1101
   struct io_hdr_stats *shi;
1094
1102
   struct io_dlist *st_dev_list_i;
1095
1103
 
1096
 
   /*
1097
 
    * Under very special circumstances, STDOUT may become unavailable,
1098
 
    * This is what we try to guess here
1099
 
    */
1100
 
   if (write(STDOUT_FILENO, "", 0) == -1) {
1101
 
      perror("stdout");
1102
 
      exit(6);
1103
 
   }
 
1104
   /* Test stdout */
 
1105
   TEST_STDOUT(STDOUT_FILENO);
1104
1106
 
1105
1107
   /* Print time stamp */
1106
1108
   if (DISPLAY_TIMESTAMP(flags)) {
1107
 
      strftime(timestamp, sizeof(timestamp), "%X", rectime);
 
1109
      if (DISPLAY_ISO(flags))
 
1110
         strftime(timestamp, sizeof(timestamp), "%FT%T%z", rectime);
 
1111
      else
 
1112
         strftime(timestamp, sizeof(timestamp), "%X", rectime);
1108
1113
      printf(_("Time: %s\n"), timestamp);
1109
1114
   }
1110
1115
 
1111
 
   /*
1112
 
    * itv is multiplied by the number of processors.
1113
 
    * This is OK to compute CPU usage since the number of jiffies spent in the
1114
 
    * different modes (user, nice, etc.) is the sum of all the processors.
1115
 
    * But itv should be reduced to one processor before displaying disk or NFS
1116
 
    * utilization.
1117
 
    */
1118
 
   if (!comm_stats[!curr].uptime)
1119
 
      /*
1120
 
       * This is the first report displaying stats since system startup.
1121
 
       * Only in this case we admit that the interval may be greater
1122
 
       * than 0xffffffff, else it was an overflow.
1123
 
       */
1124
 
      itv = comm_stats[curr].uptime;
1125
 
   else
1126
 
      /* uptime in jiffies */
1127
 
      itv = (comm_stats[curr].uptime - comm_stats[!curr].uptime)
1128
 
         & 0xffffffff;
1129
 
   if (!itv)
1130
 
      itv = 1;
 
1116
   /* Interval is multiplied by the number of processors */
 
1117
   itv = get_interval(comm_stats[!curr].uptime, comm_stats[curr].uptime);
1131
1118
 
1132
1119
   if (DISPLAY_CPU(flags))
1133
1120
      /* Display CPU utilization */
1134
1121
      write_cpu_stat(curr, itv);
1135
1122
 
1136
 
   if (cpu_nr > 1) {
 
1123
   if (cpu_nr > 1)
1137
1124
      /* On SMP machines, reduce itv to one processor (see note above) */
1138
 
      if (!comm_stats[!curr].uptime0)
1139
 
         itv = comm_stats[curr].uptime0;
1140
 
      else
1141
 
         itv = (comm_stats[curr].uptime0 - comm_stats[!curr].uptime0)
1142
 
            & 0xffffffff;
1143
 
      if (!itv)
1144
 
         itv = 1;
1145
 
   }
 
1125
      itv = get_interval(comm_stats[!curr].uptime0, comm_stats[curr].uptime0);
1146
1126
 
1147
1127
   if (DISPLAY_DISK(flags)) {
1148
1128
      struct io_stats *ioi, *ioj;
1165
1145
            if (dlist_idx && !HAS_SYSFS(flags)) {
1166
1146
               /*
1167
1147
                * With sysfs, only stats for the requested devices are read.
1168
 
                * With /proc/{diskstats,partitions}, stats for every devices
 
1148
                * With /proc/{diskstats,partitions}, stats for every device
1169
1149
                * are read. Thus we need to check if stats for current device
1170
1150
                * are to be displayed.
1171
1151
                */
1175
1155
                     break;
1176
1156
               }
1177
1157
               if (dev == dlist_idx)
1178
 
                  /* Device not found in list: don't display it */
 
1158
                  /* Device not found in list: Don't display it */
1179
1159
                  continue;
1180
1160
            }
1181
1161
        
1233
1213
 
1234
1214
/*
1235
1215
 ***************************************************************************
1236
 
 * Main loop: read I/O stats from the relevant sources,
1237
 
 * and display them.
 
1216
 * Main loop: Read I/O stats from the relevant sources and display them
1238
1217
 ***************************************************************************
1239
1218
 */
1240
1219
void rw_io_stat_loop(int flags, long int count, struct tm *rectime)
1243
1222
   int next;
1244
1223
 
1245
1224
   do {
 
1225
      if (cpu_nr > 1) {
 
1226
         /*
 
1227
          * Read system uptime (only for SMP machines).
 
1228
          * Init uptime0. So if /proc/uptime cannot fill it, this will be
 
1229
          * done by /proc/stat.
 
1230
          */
 
1231
         comm_stats[curr].uptime0 = 0;
 
1232
         readp_uptime(&(comm_stats[curr].uptime0));
 
1233
      }
 
1234
 
1246
1235
      /* Read kernel statistics (CPU, and possibly disks for old kernels) */
1247
1236
      read_proc_stat(curr, flags);
1248
1237
 
1275
1264
      if (HAS_NFS(flags))
1276
1265
         read_nfs_stat(curr, flags);
1277
1266
 
1278
 
      /* Save time */
 
1267
      /* Get time */
1279
1268
      get_localtime(rectime);
1280
1269
 
1281
1270
      /* Print results */
1282
 
      if ((next = write_stat(curr, flags, rectime))
 
1271
      if ((next = write_stats(curr, flags, rectime))
1283
1272
          && (count > 0))
1284
1273
         count--;
1285
1274
      fflush(stdout);
1370
1359
               flags |= I_D_MEGABYTES;  /* Display stats in MB/s */
1371
1360
               break;
1372
1361
        
 
1362
             case 'N':
 
1363
               flags |= I_D_DEVMAP_NAME;        /* Display device mapper logical name */
 
1364
               break;
 
1365
               
1373
1366
             case 'n':
1374
1367
               flags |= I_D_NFS;        /* Display NFS stats */
1375
1368
               break;
1410
1403
         it = 1;
1411
1404
      }
1412
1405
 
1413
 
      else {
 
1406
      else if (it > 0) {
1414
1407
         count = atol(argv[opt++]);
1415
1408
         if (count < 1)
1416
1409
           usage(argv[0]);
 
1410
         it = -1;
1417
1411
      }
 
1412
      else
 
1413
         usage(argv[0]);
1418
1414
   }
1419
1415
 
1420
1416
   /* Default: Display CPU and DISK reports */
1445
1441
 
1446
1442
   /* Get system name, release number and hostname */
1447
1443
   uname(&header);
1448
 
   print_gal_header(&rectime,
1449
 
                    header.sysname, header.release, header.nodename);
 
1444
   if (print_gal_header(&rectime,
 
1445
                        header.sysname, header.release, header.nodename))
 
1446
      flags |= I_D_ISO;
1450
1447
   printf("\n");
1451
1448
 
1452
1449
   /* Set a handler for SIGALRM */