From 57078424574814813a4f36141b8426cec1b3f7e7 Mon Sep 17 00:00:00 2001 From: Sebastien Date: Thu, 19 Jul 2012 21:18:06 +0200 Subject: [PATCH] Make sysstat disk counters consistent with those from latest kernel (3.5). Changed the type of some disk counters to keep in sync with latest 3.5 kernel. This breaks the compatibility with older sar data files format for disk activity. Mail from Peter Schiffer (pschiffe@redhat.com) 15/02/2012: I am sending you next patch. I've updated reading /proc/diskstats and /sys/block//stat files in iostat.c and rd_stats.c source files according to latest kernel (3.2.6). Problem was, that in case of very high I/O operations, sar -d and iostat outputted overflowed values: sar -d output: 09:20:01 PM DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util 09:50:01 PM sdb1 2986.02 0.05 34704.99 11.62 3355.91 1137.22 0.28 84.49 09:55:01 PM sdb1 3284.08 0.21 32884.03 10.01 4556.98 1386.29 0.27 88.31 10:00:01 PM sdb1 3260.33 0.19 31497.61 9.66 61474802782539.38 18855397092136.58 0.27 87.60 10:05:01 PM sdb1 3373.57 0.08 32028.26 9.49 6069.53 1799.10 0.27 89.86 What do you think about the patch? --- CHANGES | 6 +++++- activity.c | 6 +++--- iostat.c | 31 ++++++++++++++----------------- iostat.h | 27 +++++++++------------------ rd_stats.c | 21 +++++++++------------ rd_stats.h | 30 +++++++++++++++--------------- 6 files changed, 55 insertions(+), 66 deletions(-) diff --git a/CHANGES b/CHANGES index 2c493b7..d2fd2ad 100644 --- a/CHANGES +++ b/CHANGES @@ -1,9 +1,13 @@ Changes: xxxx/xx/xx: Version 10.1.1 - Sebastien Godard (sysstat orange.fr) + * Added option -[0-9]+ to sar to show data of that days ago. * [Peter Schiffer]: Persistent device names support added to sar and iostat (option -j). - * Added option -[0-9]+ to sar to show data of that days ago. + * [Peter Schiffer]: Make sysstat disk counters consistent + with those from latest kernel (3.5). Warning: This breaks + compatibility with older sar data files format for disk + activity. * [Peter Schiffer]: sar: Use /sys/dev/block/major:minor links to determine devices real name. * [Peter Schiffer]: Various cosmetic changes in manual pages diff --git a/activity.c b/activity.c index 32c1e46..c73bca3 100644 --- a/activity.c +++ b/activity.c @@ -1,6 +1,6 @@ /* * activity.c: Define system activities available for sar/sadc. - * (C) 1999-2011 by Sebastien GODARD (sysstat orange.fr) + * (C) 1999-2012 by Sebastien GODARD (sysstat orange.fr) * *************************************************************************** * This program is free software; you can redistribute it and/or modify it * @@ -227,7 +227,7 @@ struct activity paging_act = { struct activity io_act = { .id = A_IO, .options = AO_COLLECTED, - .magic = ACTIVITY_MAGIC_BASE, + .magic = ACTIVITY_MAGIC_BASE + 1, .group = G_DEFAULT, #ifdef SOURCE_SADC .f_count = NULL, @@ -384,7 +384,7 @@ struct activity serial_act = { struct activity disk_act = { .id = A_DISK, .options = AO_NULL, - .magic = ACTIVITY_MAGIC_BASE, + .magic = ACTIVITY_MAGIC_BASE + 1, .group = G_DISK, #ifdef SOURCE_SADC .f_count = wrap_get_disk_nr, diff --git a/iostat.c b/iostat.c index 28a169b..deefa17 100644 --- a/iostat.c +++ b/iostat.c @@ -497,15 +497,15 @@ int read_sysfs_file_stat(int curr, char *filename, char *dev_name) FILE *fp; struct io_stats sdev; int i; - unsigned long rd_ios, rd_merges_or_rd_sec, rd_ticks_or_wr_sec, wr_ios; - unsigned long ios_pgr, tot_ticks, rq_ticks, wr_merges, wr_ticks; - unsigned long long rd_sec_or_wr_ios, wr_sec; + unsigned int ios_pgr, tot_ticks, rq_ticks, wr_ticks; + unsigned long rd_ios, rd_merges_or_rd_sec, wr_ios, wr_merges; + unsigned long rd_sec_or_wr_ios, wr_sec, rd_ticks_or_wr_sec; /* Try to read given stat file */ if ((fp = fopen(filename, "r")) == NULL) return 0; - i = fscanf(fp, "%lu %lu %llu %lu %lu %lu %llu %lu %lu %lu %lu", + i = fscanf(fp, "%lu %lu %lu %lu %lu %lu %lu %u %u %u %u", &rd_ios, &rd_merges_or_rd_sec, &rd_sec_or_wr_ios, &rd_ticks_or_wr_sec, &wr_ios, &wr_merges, &wr_sec, &wr_ticks, &ios_pgr, &tot_ticks, &rq_ticks); @@ -514,7 +514,7 @@ int read_sysfs_file_stat(int curr, char *filename, char *dev_name) sdev.rd_ios = rd_ios; sdev.rd_merges = rd_merges_or_rd_sec; sdev.rd_sectors = rd_sec_or_wr_ios; - sdev.rd_ticks = rd_ticks_or_wr_sec; + sdev.rd_ticks = (unsigned int) rd_ticks_or_wr_sec; sdev.wr_ios = wr_ios; sdev.wr_merges = wr_merges; sdev.wr_sectors = wr_sec; @@ -689,9 +689,9 @@ void read_diskstats_stat(int curr) char *dm_name; struct io_stats sdev; int i; + unsigned int ios_pgr, tot_ticks, rq_ticks, wr_ticks; unsigned long rd_ios, rd_merges_or_rd_sec, rd_ticks_or_wr_sec, wr_ios; - unsigned long ios_pgr, tot_ticks, rq_ticks, wr_merges, wr_ticks; - unsigned long long rd_sec_or_wr_ios, wr_sec; + unsigned long wr_merges, rd_sec_or_wr_ios, wr_sec; char *ioc_dname; unsigned int major, minor; @@ -704,7 +704,7 @@ void read_diskstats_stat(int curr) while (fgets(line, 256, fp) != NULL) { /* major minor name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq */ - i = sscanf(line, "%u %u %s %lu %lu %llu %lu %lu %lu %llu %lu %lu %lu %lu", + i = sscanf(line, "%u %u %s %lu %lu %lu %lu %lu %lu %lu %u %u %u %u", &major, &minor, dev_name, &rd_ios, &rd_merges_or_rd_sec, &rd_sec_or_wr_ios, &rd_ticks_or_wr_sec, &wr_ios, &wr_merges, &wr_sec, &wr_ticks, &ios_pgr, &tot_ticks, &rq_ticks); @@ -717,7 +717,7 @@ void read_diskstats_stat(int curr) sdev.rd_ios = rd_ios; sdev.rd_merges = rd_merges_or_rd_sec; sdev.rd_sectors = rd_sec_or_wr_ios; - sdev.rd_ticks = rd_ticks_or_wr_sec; + sdev.rd_ticks = (unsigned int) rd_ticks_or_wr_sec; sdev.wr_ios = wr_ios; sdev.wr_merges = wr_merges; sdev.wr_sectors = wr_sec; @@ -1158,10 +1158,10 @@ void write_stats(int curr, struct tm *rectime) #ifdef DEBUG if (DISPLAY_DEBUG(flags)) { /* Debug output */ - fprintf(stderr, "name=%s itv=%llu fctr=%d ioi{ rd_sectors=%llu " - "wr_sectors=%llu rd_ios=%lu rd_merges=%lu rd_ticks=%lu " - "wr_ios=%lu wr_merges=%lu wr_ticks=%lu ios_pgr=%lu tot_ticks=%lu " - "rq_ticks=%lu dk_drive=%lu dk_drive_rblk=%lu dk_drive_wblk=%lu }\n", + fprintf(stderr, "name=%s itv=%llu fctr=%d ioi{ rd_sectors=%lu " + "wr_sectors=%lu rd_ios=%lu rd_merges=%lu rd_ticks=%u " + "wr_ios=%lu wr_merges=%lu wr_ticks=%u ios_pgr=%u tot_ticks=%u " + "rq_ticks=%u }\n", shi->name, itv, fctr, @@ -1175,10 +1175,7 @@ void write_stats(int curr, struct tm *rectime) ioi->wr_ticks, ioi->ios_pgr, ioi->tot_ticks, - ioi->rq_ticks, - ioi->dk_drive, - ioi->dk_drive_rblk, - ioi->dk_drive_wblk + ioi->rq_ticks ); } #endif diff --git a/iostat.h b/iostat.h index 281689d..e01f058 100644 --- a/iostat.h +++ b/iostat.h @@ -60,10 +60,7 @@ * The number of structures allocated corresponds to the number of devices * present in the system, plus a preallocation number to handle those * that can be registered dynamically. - * The number of devices is found by using /sys filesystem (if mounted), - * or the number of "disk_io:" entries in /proc/stat (2.4 kernels), - * else the default value is 4 (for old kernels, which maintained stats - * for the first four devices in /proc/stat). + * The number of devices is found by using /sys filesystem (if mounted). * For each io_stats structure allocated corresponds a io_hdr_stats structure. * A io_stats structure is considered as unused or "free" (containing no stats * for a particular device) if the 'major' field of the io_hdr_stats @@ -71,33 +68,27 @@ */ struct io_stats { /* # of sectors read */ - unsigned long long rd_sectors __attribute__ ((aligned (8))); + unsigned long rd_sectors __attribute__ ((aligned (8))); /* # of sectors written */ - unsigned long long wr_sectors __attribute__ ((packed)); + unsigned long wr_sectors __attribute__ ((packed)); /* # of read operations issued to the device */ unsigned long rd_ios __attribute__ ((packed)); /* # of read requests merged */ unsigned long rd_merges __attribute__ ((packed)); - /* Time of read requests in queue */ - unsigned long rd_ticks __attribute__ ((packed)); /* # of write operations issued to the device */ unsigned long wr_ios __attribute__ ((packed)); /* # of write requests merged */ unsigned long wr_merges __attribute__ ((packed)); + /* Time of read requests in queue */ + unsigned int rd_ticks __attribute__ ((packed)); /* Time of write requests in queue */ - unsigned long wr_ticks __attribute__ ((packed)); + unsigned int wr_ticks __attribute__ ((packed)); /* # of I/Os in progress */ - unsigned long ios_pgr __attribute__ ((packed)); + unsigned int ios_pgr __attribute__ ((packed)); /* # of ticks total (for this device) for I/O */ - unsigned long tot_ticks __attribute__ ((packed)); + unsigned int tot_ticks __attribute__ ((packed)); /* # of ticks requests spent in queue */ - unsigned long rq_ticks __attribute__ ((packed)); - /* # of I/O done since last reboot */ - unsigned long dk_drive __attribute__ ((packed)); - /* # of blocks read */ - unsigned long dk_drive_rblk __attribute__ ((packed)); - /* # of blocks written */ - unsigned long dk_drive_wblk __attribute__ ((packed)); + unsigned int rq_ticks __attribute__ ((packed)); }; #define IO_STATS_SIZE (sizeof(struct io_stats)) diff --git a/rd_stats.c b/rd_stats.c index 7da6b70..1a07d7c 100644 --- a/rd_stats.c +++ b/rd_stats.c @@ -1,6 +1,6 @@ /* * rd_stats.c: Read system statistics - * (C) 1999-2011 by Sebastien GODARD (sysstat orange.fr) + * (C) 1999-2012 by Sebastien GODARD (sysstat orange.fr) * *************************************************************************** * This program is free software; you can redistribute it and/or modify it * @@ -472,15 +472,14 @@ void read_diskstats_io(struct stats_io *st_io) char line[256]; char dev_name[MAX_NAME_LEN]; unsigned int major, minor; - unsigned long rd_ios, wr_ios; - unsigned long long rd_sec, wr_sec; + unsigned long rd_ios, wr_ios, rd_sec, wr_sec; if ((fp = fopen(DISKSTATS, "r")) == NULL) return; while (fgets(line, 256, fp) != NULL) { - if (sscanf(line, "%u %u %s %lu %*u %llu %*u %lu %*u %llu", + if (sscanf(line, "%u %u %s %lu %*u %lu %*u %lu %*u %lu", &major, &minor, dev_name, &rd_ios, &rd_sec, &wr_ios, &wr_sec) == 7) { @@ -491,9 +490,9 @@ void read_diskstats_io(struct stats_io *st_io) */ st_io->dk_drive += rd_ios + wr_ios; st_io->dk_drive_rio += rd_ios; - st_io->dk_drive_rblk += (unsigned int) rd_sec; + st_io->dk_drive_rblk += rd_sec; st_io->dk_drive_wio += wr_ios; - st_io->dk_drive_wblk += (unsigned int) wr_sec; + st_io->dk_drive_wblk += wr_sec; } } } @@ -522,18 +521,16 @@ void read_diskstats_disk(struct stats_disk *st_disk, int nbr, int read_part) char dev_name[MAX_NAME_LEN]; int dsk = 0; struct stats_disk *st_disk_i; - unsigned int major, minor; - unsigned long rd_ios, wr_ios, rd_ticks, wr_ticks; - unsigned long tot_ticks, rq_ticks; - unsigned long long rd_sec, wr_sec; + unsigned int major, minor, rd_ticks, wr_ticks, tot_ticks, rq_ticks; + unsigned long rd_ios, wr_ios, rd_sec, wr_sec; if ((fp = fopen(DISKSTATS, "r")) == NULL) return; while ((fgets(line, 256, fp) != NULL) && (dsk < nbr)) { - if (sscanf(line, "%u %u %s %lu %*u %llu %lu %lu %*u %llu" - " %lu %*u %lu %lu", + if (sscanf(line, "%u %u %s %lu %*u %lu %u %lu %*u %lu" + " %u %*u %u %u", &major, &minor, dev_name, &rd_ios, &rd_sec, &rd_ticks, &wr_ios, &wr_sec, &wr_ticks, &tot_ticks, &rq_ticks) == 11) { diff --git a/rd_stats.h b/rd_stats.h index 23f854f..defe91c 100644 --- a/rd_stats.h +++ b/rd_stats.h @@ -1,6 +1,6 @@ /* * rd_stats.h: Include file used to read system statistics - * (C) 1999-2011 by Sebastien Godard (sysstat orange.fr) + * (C) 1999-2012 by Sebastien Godard (sysstat orange.fr) */ #ifndef _RD_STATS_H @@ -137,11 +137,11 @@ struct stats_paging { /* Structure for I/O and transfer rate statistics */ struct stats_io { - unsigned int dk_drive __attribute__ ((aligned (4))); - unsigned int dk_drive_rio __attribute__ ((packed)); - unsigned int dk_drive_wio __attribute__ ((packed)); - unsigned int dk_drive_rblk __attribute__ ((packed)); - unsigned int dk_drive_wblk __attribute__ ((packed)); + unsigned long long dk_drive __attribute__ ((aligned (16))); + unsigned long long dk_drive_rio __attribute__ ((packed)); + unsigned long long dk_drive_wio __attribute__ ((packed)); + unsigned long long dk_drive_rblk __attribute__ ((packed)); + unsigned long long dk_drive_wblk __attribute__ ((packed)); }; #define STATS_IO_SIZE (sizeof(struct stats_io)) @@ -203,15 +203,15 @@ struct stats_serial { /* Structure for block devices statistics */ struct stats_disk { - unsigned long long rd_sect __attribute__ ((aligned (16))); - unsigned long long wr_sect __attribute__ ((aligned (16))); - unsigned long rd_ticks __attribute__ ((aligned (16))); - unsigned long wr_ticks __attribute__ ((aligned (8))); - unsigned long tot_ticks __attribute__ ((aligned (8))); - unsigned long rq_ticks __attribute__ ((aligned (8))); - unsigned long nr_ios __attribute__ ((aligned (8))); - unsigned int major __attribute__ ((aligned (8))); - unsigned int minor __attribute__ ((packed)); + unsigned long long nr_ios __attribute__ ((aligned (16))); + unsigned long rd_sect __attribute__ ((aligned (16))); + unsigned long wr_sect __attribute__ ((aligned (8))); + unsigned int rd_ticks __attribute__ ((aligned (8))); + unsigned int wr_ticks __attribute__ ((packed)); + unsigned int tot_ticks __attribute__ ((packed)); + unsigned int rq_ticks __attribute__ ((packed)); + unsigned int major __attribute__ ((packed)); + unsigned int minor __attribute__ ((packed)); }; #define STATS_DISK_SIZE (sizeof(struct stats_disk)) -- 2.40.0