]> granicus.if.org Git - sysstat/blobdiff - rd_stats.c
sar/sadc: Add stable identifier support for disks statistics
[sysstat] / rd_stats.c
index d4a938b35e11a0d55ed3c901755c9fd16e1c8053..2569fae28e8c91f9d8fd71e820e4bed36c4ffdc8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * rd_stats.c: Read system statistics
- * (C) 1999-2018 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 1999-2019 by Sebastien GODARD (sysstat <at> orange.fr)
  *
  ***************************************************************************
  * This program is free software; you can redistribute it and/or modify it *
@@ -375,10 +375,10 @@ void compute_ext_disk_stats(struct stats_disk *sdc, struct stats_disk *sdp,
         * => no need for further scaling.
         */
        xds->await = (sdc->nr_ios - sdp->nr_ios) ?
-               ((sdc->rd_ticks - sdp->rd_ticks) + (sdc->wr_ticks - sdp->wr_ticks)) /
+               ((sdc->rd_ticks - sdp->rd_ticks) + (sdc->wr_ticks - sdp->wr_ticks) + (sdc->dc_ticks - sdp->dc_ticks)) /
                ((double) (sdc->nr_ios - sdp->nr_ios)) : 0.0;
        xds->arqsz = (sdc->nr_ios - sdp->nr_ios) ?
-               ((sdc->rd_sect - sdp->rd_sect) + (sdc->wr_sect - sdp->wr_sect)) /
+               ((sdc->rd_sect - sdp->rd_sect) + (sdc->wr_sect - sdp->wr_sect) + (sdc->dc_sect - sdp->dc_sect)) /
                ((double) (sdc->nr_ios - sdp->nr_ios)) : 0.0;
 }
 
@@ -722,27 +722,42 @@ __nr_t read_diskstats_io(struct stats_io *st_io)
        char line[1024];
        char dev_name[MAX_NAME_LEN];
        unsigned int major, minor;
-       unsigned long rd_ios, wr_ios, rd_sec, wr_sec;
+       unsigned long rd_ios, wr_ios, dc_ios;
+       unsigned long rd_sec, wr_sec, dc_sec;
 
        if ((fp = fopen(DISKSTATS, "r")) == NULL)
                return 0;
 
        while (fgets(line, sizeof(line), fp) != NULL) {
 
-               if (sscanf(line, "%u %u %s %lu %*u %lu %*u %lu %*u %lu",
+               /* Discard I/O stats may be not available */
+               dc_ios = dc_sec = 0;
+
+               if (sscanf(line,
+                          "%u %u %s "
+                          "%lu %*u %lu %*u "
+                          "%lu %*u %lu %*u "
+                          "%*u %*u %*u "
+                          "%lu %*u %lu",
                           &major, &minor, dev_name,
-                          &rd_ios, &rd_sec, &wr_ios, &wr_sec) == 7) {
+                          &rd_ios, &rd_sec,
+                          &wr_ios, &wr_sec,
+                          &dc_ios, &dc_sec) >= 7) {
 
                        if (is_device(dev_name, IGNORE_VIRTUAL_DEVICES)) {
                                /*
                                 * OK: It's a (real) device and not a partition.
                                 * Note: Structure should have been initialized first!
                                 */
-                               st_io->dk_drive      += (unsigned long long) rd_ios + (unsigned long long) wr_ios;
+                               st_io->dk_drive      += (unsigned long long) rd_ios +
+                                                       (unsigned long long) wr_ios +
+                                                       (unsigned long long) dc_ios;
                                st_io->dk_drive_rio  += rd_ios;
                                st_io->dk_drive_rblk += rd_sec;
                                st_io->dk_drive_wio  += wr_ios;
                                st_io->dk_drive_wblk += wr_sec;
+                               st_io->dk_drive_dio  += dc_ios;
+                               st_io->dk_drive_dblk += dc_sec;
                        }
                }
        }
@@ -776,8 +791,9 @@ __nr_t read_diskstats_disk(struct stats_disk *st_disk, __nr_t nr_alloc,
        char line[1024];
        char dev_name[MAX_NAME_LEN];
        struct stats_disk *st_disk_i;
-       unsigned int major, minor, rd_ticks, wr_ticks, tot_ticks, rq_ticks;
-       unsigned long rd_ios, wr_ios, rd_sec, wr_sec;
+       unsigned int major, minor, rd_ticks, wr_ticks, dc_ticks, tot_ticks, rq_ticks, part_nr;
+       unsigned long rd_ios, wr_ios, dc_ios, rd_sec, wr_sec, dc_sec;
+       unsigned long long wwn[2];
        __nr_t dsk_read = 0;
 
        if ((fp = fopen(DISKSTATS, "r")) == NULL)
@@ -785,13 +801,22 @@ __nr_t read_diskstats_disk(struct stats_disk *st_disk, __nr_t nr_alloc,
 
        while (fgets(line, sizeof(line), fp) != NULL) {
 
-               if (sscanf(line, "%u %u %s %lu %*u %lu %u %lu %*u %lu"
-                          " %u %*u %u %u",
+               /* Discard I/O stats may be not available */
+               dc_ios = dc_sec = dc_ticks = 0;
+
+               if (sscanf(line,
+                          "%u %u %s "
+                          "%lu %*u %lu %u "
+                          "%lu %*u %lu %u "
+                          "%*u %u %u "
+                          "%lu %*u %lu %u",
                           &major, &minor, dev_name,
-                          &rd_ios, &rd_sec, &rd_ticks, &wr_ios, &wr_sec, &wr_ticks,
-                          &tot_ticks, &rq_ticks) == 11) {
+                          &rd_ios, &rd_sec, &rd_ticks,
+                          &wr_ios, &wr_sec, &wr_ticks,
+                          &tot_ticks, &rq_ticks,
+                          &dc_ios, &dc_sec, &dc_ticks) >= 11) {
 
-                       if (!rd_ios && !wr_ios)
+                       if (!rd_ios && !wr_ios && !dc_ios)
                                /* Unused device: Ignore it */
                                continue;
                        if (read_part || is_device(dev_name, ACCEPT_VIRTUAL_DEVICES)) {
@@ -804,13 +829,26 @@ __nr_t read_diskstats_disk(struct stats_disk *st_disk, __nr_t nr_alloc,
                                st_disk_i = st_disk + dsk_read++;
                                st_disk_i->major     = major;
                                st_disk_i->minor     = minor;
-                               st_disk_i->nr_ios    = (unsigned long long) rd_ios + (unsigned long long) wr_ios;
+                               st_disk_i->nr_ios    = (unsigned long long) rd_ios +
+                                                      (unsigned long long) wr_ios +
+                                                      (unsigned long long) dc_ios;
                                st_disk_i->rd_sect   = rd_sec;
                                st_disk_i->wr_sect   = wr_sec;
+                               st_disk_i->dc_sect   = dc_sec;
                                st_disk_i->rd_ticks  = rd_ticks;
                                st_disk_i->wr_ticks  = wr_ticks;
+                               st_disk_i->dc_ticks  = dc_ticks;
                                st_disk_i->tot_ticks = tot_ticks;
                                st_disk_i->rq_ticks  = rq_ticks;
+
+                               if (get_wwnid_from_pretty(dev_name, wwn, &part_nr) < 0) {
+                                       st_disk_i->wwn[0] = 0ULL;
+                               }
+                               else {
+                                       st_disk_i->wwn[0] = wwn[0];
+                                       st_disk_i->wwn[1] = wwn[1];
+                                       st_disk_i->part_nr = part_nr;
+                               }
                        }
                }
        }
@@ -1517,6 +1555,7 @@ __nr_t read_net_eicmp(struct stats_net_eicmp *st_net_eicmp)
 {
        FILE *fp;
        char line[1024];
+       static char format[256] = "";
        int sw = FALSE;
 
        if ((fp = fopen(NET_SNMP, "r")) == NULL)
@@ -1526,8 +1565,7 @@ __nr_t read_net_eicmp(struct stats_net_eicmp *st_net_eicmp)
 
                if (!strncmp(line, "Icmp:", 5)) {
                        if (sw) {
-                               sscanf(line + 5, "%*u %lu %lu %lu %lu %lu %lu %*u %*u "
-                                      "%*u %*u %*u %*u %*u %lu %lu %lu %lu %lu %lu",
+                               sscanf(line + 5, format,
                                       &st_net_eicmp->InErrors,
                                       &st_net_eicmp->InDestUnreachs,
                                       &st_net_eicmp->InTimeExcds,
@@ -1544,6 +1582,25 @@ __nr_t read_net_eicmp(struct stats_net_eicmp *st_net_eicmp)
                                break;
                        }
                        else {
+                               if (!strlen(format)) {
+                                       if (strstr(line, "InCsumErrors")) {
+                                               /*
+                                                * New format: InCsumErrors field exists at position #3.
+                                                * Capture: 2,4,5,6,7,8,16,17,18,19,20,21
+                                                */
+                                               strcpy(format, "%*u %lu %*u %lu %lu %lu %lu %lu %*u %*u "
+                                                              "%*u %*u %*u %*u %*u %lu %lu %lu %lu %lu %lu");
+                                       }
+                                       else {
+                                               /*
+                                                * Old format: InCsumErrors field doesn't exist.
+                                                * Capture: 2,3,4,5,6,7,15,16,17,18,19,20
+                                                */
+                                               strcpy(format, "%*u %lu %lu %lu %lu %lu %lu %*u %*u "
+                                                              "%*u %*u %*u %*u %*u %lu %lu %lu %lu %lu %lu");
+
+                                       }
+                               }
                                sw = TRUE;
                        }
                }
@@ -2436,9 +2493,9 @@ __nr_t read_bus_usb_dev(struct stats_pwr_usb *st_pwr_usb, __nr_t nr_alloc)
 __nr_t read_filesystem(struct stats_filesystem *st_filesystem, __nr_t nr_alloc)
 {
        FILE *fp;
-       char line[512], fs_name[128], mountp[256];
+       char line[512], fs_name[MAX_FS_LEN], mountp[256], type[128];
        int skip = 0, skip_next = 0;
-       char *pos = 0;
+       char *pos = 0, *pos2 = 0;
        __nr_t fs_read = 0;
        struct stats_filesystem *st_filesystem_i;
        struct statvfs buf;
@@ -2463,6 +2520,19 @@ __nr_t read_filesystem(struct stats_filesystem *st_filesystem, __nr_t nr_alloc)
                        if (pos == NULL)
                                continue;
 
+                       /*
+                        * Find second field separator position,
+                        * read filesystem type,
+                        * if filesystem type is autofs, skip it
+                       */
+                       pos2 = strchr(pos + 1, ' ');
+                       if (pos2 == NULL)
+                               continue;
+
+                       sscanf(pos2 + 1, "%127s", type);
+                       if(strcmp(type, "autofs") == 0)
+                               continue;
+
                        /* Read current filesystem name */
                        sscanf(line, "%127s", fs_name);
                        /*
@@ -2483,7 +2553,7 @@ __nr_t read_filesystem(struct stats_filesystem *st_filesystem, __nr_t nr_alloc)
                         * It's important to have read the whole mount point name
                         * for statvfs() to work properly (see above).
                         */
-                       if ((statvfs(mountp, &buf) < 0) || (!buf.f_blocks))
+                       if ((__statvfs(mountp, &buf) < 0) || (!buf.f_blocks))
                                continue;
 
                        if (fs_read + 1 > nr_alloc) {
@@ -2536,14 +2606,14 @@ __nr_t read_fchost(struct stats_fchost *st_fc, __nr_t nr_alloc)
        unsigned long rx_frames, tx_frames, rx_words, tx_words;
 
        /* Each host, if present, will have its own hostX entry within SYSFS_FCHOST */
-       if ((dir = opendir(SYSFS_FCHOST)) == NULL)
+       if ((dir = __opendir(SYSFS_FCHOST)) == NULL)
                return 0; /* No FC hosts */
 
        /*
         * Read each of the counters via sysfs, where they are
         * returned as hex values (e.g. 0x72400).
         */
-       while ((drd = readdir(dir)) != NULL) {
+       while ((drd = __readdir(dir)) != NULL) {
                rx_frames = tx_frames = rx_words = tx_words = 0;
 
                if (!strncmp(drd->d_name, "host", 4)) {
@@ -2594,12 +2664,12 @@ __nr_t read_fchost(struct stats_fchost *st_fc, __nr_t nr_alloc)
                        st_fc_i->f_txframes = tx_frames;
                        st_fc_i->f_rxwords  = rx_words;
                        st_fc_i->f_txwords  = tx_words;
-                       strncpy(st_fc_i->fchost_name, drd->d_name, MAX_FCH_LEN);
+                       memcpy(st_fc_i->fchost_name, drd->d_name, MAX_FCH_LEN);
                        st_fc_i->fchost_name[MAX_FCH_LEN - 1] = '\0';
                }
        }
 
-       closedir(dir);
+       __closedir(dir);
        return fch_read;
 }