From c288c900e7b46fc8718941978f21ce9d14579920 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 10 2018 05:47:49 +0000 Subject: import sysstat-10.1.5-13.el7 --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c9bcdbe --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/sysstat-10.1.5.tar.bz2 diff --git a/.sysstat.metadata b/.sysstat.metadata new file mode 100644 index 0000000..3cf7ea8 --- /dev/null +++ b/.sysstat.metadata @@ -0,0 +1 @@ +637258b7881446317079a80be497a013105b2b20 SOURCES/sysstat-10.1.5.tar.bz2 diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/0001-pidstat-Display-stats-since-boot-time-for-a-list-of-.patch b/SOURCES/0001-pidstat-Display-stats-since-boot-time-for-a-list-of-.patch new file mode 100644 index 0000000..662c6a1 --- /dev/null +++ b/SOURCES/0001-pidstat-Display-stats-since-boot-time-for-a-list-of-.patch @@ -0,0 +1,52 @@ +From b4cad00cfb3086490261db7202de8ed846e79344 Mon Sep 17 00:00:00 2001 +From: Sebastien GODARD +Date: Wed, 2 Oct 2013 09:55:38 +0200 +Subject: [PATCH] pidstat: Display stats since boot time for a list of given + processes + +pidstat displays statistics since system startup when the interval and +count parameters are not set on the command line (eg. entering "pidstat +-d" will display I/O statistics for all processes that have had I/O +activity since boot time). But pidstat couldn't display those stats when +some PID numbers were entered on the command line (eg. "pidstat -d -p +1234" to display I/O stats since system startup for process 1234). +This patch makes it possible now. + +Signed-off-by: Sebastien GODARD +(cherry picked from commit 18c7a03f52826942a720b2a0cc32e1f074784c6a) + +Resolves: #1448489 +--- + pidstat.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/pidstat.c b/pidstat.c +index 3bb98f2..85d4d98 100644 +--- a/pidstat.c ++++ b/pidstat.c +@@ -1048,10 +1048,18 @@ int get_pid_to_display(int prev, int curr, int p, unsigned int activity, + + else if (DISPLAY_PID(pidflag)) { + *pstp = st_pid_list[prev] + p; +- +- if (!(*pstp)->pid) +- /* PID no longer exists */ +- return 0; ++ if (!(*pstp)->pid) { ++ if (interval) ++ /* PID no longer exists */ ++ return 0; ++ else { ++ /* ++ * If interval is null, then we are trying to ++ * display stats for a given process since boot time. ++ */ ++ *pstp = &st_pid_null; ++ } ++ } + } + + if (COMMAND_STRING(pidflag)) { +-- +2.13.6 + diff --git a/SOURCES/0001-sar-Improve-cpuinfo-read-for-POWER-architecture.patch b/SOURCES/0001-sar-Improve-cpuinfo-read-for-POWER-architecture.patch new file mode 100644 index 0000000..97556de --- /dev/null +++ b/SOURCES/0001-sar-Improve-cpuinfo-read-for-POWER-architecture.patch @@ -0,0 +1,47 @@ +From 81ef06797b16d08a4558a41891b9d9421a0a96f8 Mon Sep 17 00:00:00 2001 +From: Breno Leitao +Date: Mon, 31 Oct 2016 09:23:59 -0400 +Subject: [PATCH] sar: Improve cpuinfo read for POWER architecture + +Currently CPU frequency is not being read properly on POWER archicture. +It shows the frequency as: + # sar -m CPU 1 5 +... + 06:30:28 AM CPU MHz + 06:30:36 AM all 0.00 + +This is caused because /proc/cpuinfo is differently between Intel and +POWER. +This patch simply fix the parsing function (read_cpuinfo). + +Signed-off-by: Breno Leitao + +Resolves: #1440000 +--- + rd_stats.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/rd_stats.c b/rd_stats.c +index dafd975..d8c337a 100644 +--- a/rd_stats.c ++++ b/rd_stats.c +@@ -1625,10 +1625,12 @@ void read_cpuinfo(struct stats_pwr_cpufreq *st_pwr_cpufreq, int nbr) + if (!strncmp(line, "processor\t", 10)) { + sscanf(strchr(line, ':') + 1, "%d", &proc_nb); + } +- +- else if (!strncmp(line, "cpu MHz\t", 8)) { +- sscanf(strchr(line, ':') + 1, "%u.%u", &ifreq, &dfreq); +- ++ ++ /* Entry in /proc/cpuinfo is different between Intel and Power architectures */ ++ else if (!strncmp(line, "cpu MHz\t", 8) || ++ !strncmp(line, "clock\t", 6)) { ++ sscanf(strchr(line, ':') + 1, "%u.%u", &ifreq, &dfreq); ++ + if (proc_nb < (nbr - 1)) { + /* Save current CPU frequency */ + st_pwr_cpufreq_i = st_pwr_cpufreq + proc_nb + 1; +-- +2.13.6 + diff --git a/SOURCES/0001-sar-make-buffers-that-hold-timestamps-bigger.patch b/SOURCES/0001-sar-make-buffers-that-hold-timestamps-bigger.patch new file mode 100644 index 0000000..786264a --- /dev/null +++ b/SOURCES/0001-sar-make-buffers-that-hold-timestamps-bigger.patch @@ -0,0 +1,68 @@ +From f3964e0fa19e0c33470f37014ebcebf0b4253363 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 30 Sep 2016 18:05:44 +0200 +Subject: [PATCH] sar: make buffers that hold timestamps bigger +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On systems that use Korean UTF-8 locale sar will not print timestamp +because there is not enough space in the buffer. + +I bumped buffer size to 64 bytes because I figured out that 32 bytes is +still not enough to print out timestamp when using some glibc supported +locales. + +$ LC_TIME=ko_KR.UTF-8 ./sar 1 1 + +Before: +Linux 4.7.2-201.fc24.x86_64 (morgoth.usersys.redhat.com) 2016년 09월 30일 _x86_64_ (4 CPU) + + CPU %user %nice %system %iowait %steal %idle + all 4.51 0.00 2.51 0.00 0.00 92.98 +Average: all 4.51 0.00 2.51 0.00 0.00 92.98 + +After: +Linux 4.7.2-201.fc24.x86_64 (morgoth.usersys.redhat.com) 2016년 09월 30일 _x86_64_ (4 CPU) + +18시 18분 36초 CPU %user %nice %system %iowait %steal %idle +18시 18분 37초 all 3.76 0.00 2.26 0.00 0.00 93.98 +Average: all 3.76 0.00 2.26 0.00 0.00 93.98 +--- + sa.h | 2 +- + sar.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sa.h b/sa.h +index 54e7a4e..c11dbe9 100644 +--- a/sa.h ++++ b/sa.h +@@ -199,7 +199,7 @@ + #define NR_USB_PREALLOC 5 + + #define UTSNAME_LEN 65 +-#define TIMESTAMP_LEN 16 ++#define TIMESTAMP_LEN 64 + #define HEADER_LINE_LEN 512 + + /* Maximum number of args that can be passed to sadc */ +diff --git a/sar.c b/sar.c +index e8ad83e..8dd998b 100644 +--- a/sar.c ++++ b/sar.c +@@ -469,10 +469,10 @@ int write_stats(int curr, int read_from_file, long *cnt, int use_tm_start, + } + + /* Set previous timestamp */ +- if (set_record_timestamp_string(!curr, timestamp[!curr], 16)) ++ if (set_record_timestamp_string(!curr, timestamp[!curr], TIMESTAMP_LEN)) + return 0; + /* Set current timestamp */ +- if (set_record_timestamp_string(curr, timestamp[curr], 16)) ++ if (set_record_timestamp_string(curr, timestamp[curr], TIMESTAMP_LEN)) + return 0; + + /* Check if we are beginning a new day */ +-- +2.9.3 + diff --git a/SOURCES/sysstat-10.0.0-makefile.patch b/SOURCES/sysstat-10.0.0-makefile.patch new file mode 100644 index 0000000..65f12c6 --- /dev/null +++ b/SOURCES/sysstat-10.0.0-makefile.patch @@ -0,0 +1,13 @@ +diff -up sysstat-10.0.0/Makefile.in.pom sysstat-10.0.0/Makefile.in +--- sysstat-10.0.0/Makefile.in.pom 2011-03-06 16:46:23.000000000 +0100 ++++ sysstat-10.0.0/Makefile.in 2011-04-04 10:23:02.000000000 +0200 +@@ -196,8 +196,8 @@ librdsensors.a: librdsensors.a(rd_sensor + + sadc.o: sadc.c sa.h version.h common.h ioconf.h sysconfig.h rd_stats.h rd_sensors.h + +-sadc: LFLAGS += $(LFSENSORS) + sadc: sadc.o act_sadc.o sa_wrap.o sa_common.o librdstats.a librdsensors.a libsyscom.a ++ $(CC) -o $@ $(CFLAGS) $^ $(LFLAGS) -lsensors + + sar.o: sar.c sa.h version.h common.h ioconf.h pr_stats.h sysconfig.h + diff --git a/SOURCES/sysstat-10.1.5-dyn-tick.patch b/SOURCES/sysstat-10.1.5-dyn-tick.patch new file mode 100644 index 0000000..133fa0d --- /dev/null +++ b/SOURCES/sysstat-10.1.5-dyn-tick.patch @@ -0,0 +1,48 @@ +diff -ur sysstat-10.1.5.orig/common.c sysstat-10.1.5/common.c +--- sysstat-10.1.5.orig/common.c 2013-03-23 17:31:46.000000000 +0100 ++++ sysstat-10.1.5/common.c 2014-09-01 22:29:48.173500407 +0200 +@@ -501,26 +501,13 @@ + hz = (unsigned int) ticks; + } + +-/* +- *************************************************************************** +- * Handle overflow conditions properly for counters which are read as +- * unsigned long long, but which can be unsigned long long or +- * unsigned long only depending on the kernel version used. +- * @value1 and @value2 being two values successively read for this +- * counter, if @value2 < @value1 and @value1 <= 0xffffffff, then we can +- * assume that the counter's type was unsigned long and has overflown, and +- * so the difference @value2 - @value1 must be casted to this type. +- * NOTE: These functions should no longer be necessary to handle a particular +- * stat counter when we can assume that everybody is using a recent kernel +- * (defining this counter as unsigned long long). +- *************************************************************************** +- */ + double ll_sp_value(unsigned long long value1, unsigned long long value2, + unsigned long long itv) + { +- if ((value2 < value1) && (value1 <= 0xffffffff)) +- /* Counter's type was unsigned long and has overflown */ +- return ((double) ((value2 - value1) & 0xffffffff)) / itv * 100; ++ /* Workaround: dyn-tick kernel has a race issue and /proc/stat values ++ could be backward. */ ++ if (value2 < value1) ++ return (double) 0; + else + return SP_VALUE(value1, value2, itv); + } +@@ -528,9 +515,10 @@ + double ll_s_value(unsigned long long value1, unsigned long long value2, + unsigned long long itv) + { +- if ((value2 < value1) && (value1 <= 0xffffffff)) +- /* Counter's type was unsigned long and has overflown */ +- return ((double) ((value2 - value1) & 0xffffffff)) / itv * HZ; ++ /* Workaround: dyn-tick kernel has a race issue and /proc/stat values ++ could be backward. */ ++ if (value2 < value1) ++ return (double) 0; + else + return S_VALUE(value1, value2, itv); + } diff --git a/SOURCES/sysstat-10.1.5-elapsed-time.patch b/SOURCES/sysstat-10.1.5-elapsed-time.patch new file mode 100644 index 0000000..6ecd64c --- /dev/null +++ b/SOURCES/sysstat-10.1.5-elapsed-time.patch @@ -0,0 +1,24 @@ +diff -ur sysstat-10.1.5.orig/man/iostat.in sysstat-10.1.5/man/iostat.in +--- sysstat-10.1.5.orig/man/iostat.in 2012-11-27 21:20:34.000000000 +0100 ++++ sysstat-10.1.5/man/iostat.in 2014-11-11 17:44:29.563840350 +0100 +@@ -264,7 +264,7 @@ + .RE + .B %util + .RS +-Percentage of CPU time during which I/O requests were issued to the device ++Percentage of elapsed time during which I/O requests were issued to the device + (bandwidth utilization for the device). Device saturation occurs when this + value is close to 100%. + .RE +diff -ur sysstat-10.1.5.orig/man/sar.in sysstat-10.1.5/man/sar.in +--- sysstat-10.1.5.orig/man/sar.in 2012-09-30 15:11:06.000000000 +0200 ++++ sysstat-10.1.5/man/sar.in 2014-11-11 17:45:00.682712161 +0100 +@@ -306,7 +306,7 @@ + + .B %util + .RS +-Percentage of CPU time during which I/O requests were issued to the device ++Percentage of elapsed time during which I/O requests were issued to the device + (bandwidth utilization for the device). Device saturation occurs when this + value is close to 100%. + .RE diff --git a/SOURCES/sysstat-10.1.5-int-handler.patch b/SOURCES/sysstat-10.1.5-int-handler.patch new file mode 100644 index 0000000..7a5f959 --- /dev/null +++ b/SOURCES/sysstat-10.1.5-int-handler.patch @@ -0,0 +1,27 @@ +diff -upr sysstat-10.1.5.orig/sadc.c sysstat-10.1.5/sadc.c +--- sysstat-10.1.5.orig/sadc.c 2013-03-23 17:31:46.000000000 +0100 ++++ sysstat-10.1.5/sadc.c 2016-04-29 17:52:11.438614928 +0200 +@@ -225,17 +225,19 @@ void alarm_handler(int sig) + */ + void int_handler(int sig) + { +- if (!optz) { +- /* sadc hasn't been called by sar */ ++ pid_t ppid = getppid(); ++ ++ if (!optz || (ppid == 1)) { ++ /* sadc hasn't been called by sar or sar process is already dead */ + exit(1); + } +- ++ + /* + * When starting sar then pressing ctrl/c, SIGINT is received + * by sadc, not sar. So send SIGINT to sar so that average stats + * can be displayed. + */ +- if (kill(getppid(), SIGINT) < 0) { ++ if (kill(ppid, SIGINT) < 0) { + exit(1); + } + } diff --git a/SOURCES/sysstat-10.1.5-max-cpus.patch b/SOURCES/sysstat-10.1.5-max-cpus.patch new file mode 100644 index 0000000..a593952 --- /dev/null +++ b/SOURCES/sysstat-10.1.5-max-cpus.patch @@ -0,0 +1,16 @@ +diff -upr sysstat-10.1.5.orig/common.h sysstat-10.1.5/common.h +--- sysstat-10.1.5.orig/common.h 2016-04-29 14:12:25.709765182 +0200 ++++ sysstat-10.1.5/common.h 2016-04-29 14:15:21.463578820 +0200 +@@ -28,10 +28,10 @@ + #define SEC_PER_DAY 3600 * 24 + + /* Maximum number of CPUs */ +-#if defined(__CPU_SETSIZE) && __CPU_SETSIZE > 2048 ++#if defined(__CPU_SETSIZE) && __CPU_SETSIZE > 8192 + #define NR_CPUS __CPU_SETSIZE + #else +-#define NR_CPUS 2048 ++#define NR_CPUS 8192 + #endif + + /* Maximum number of interrupts */ diff --git a/SOURCES/sysstat-10.1.5-max-name-len.patch b/SOURCES/sysstat-10.1.5-max-name-len.patch new file mode 100644 index 0000000..29fe860 --- /dev/null +++ b/SOURCES/sysstat-10.1.5-max-name-len.patch @@ -0,0 +1,35 @@ +diff -upr sysstat-10.1.5.orig/common.h sysstat-10.1.5/common.h +--- sysstat-10.1.5.orig/common.h 2016-04-29 14:29:24.298889634 +0200 ++++ sysstat-10.1.5/common.h 2016-04-29 14:30:10.589577176 +0200 +@@ -69,7 +69,7 @@ + #define MAX_FILE_LEN 256 + #define MAX_PF_NAME 1024 + #define DEFAULT_DEVMAP_MAJOR 253 +-#define MAX_NAME_LEN 72 ++#define MAX_NAME_LEN 128 + + #define IGNORE_VIRTUAL_DEVICES FALSE + #define ACCEPT_VIRTUAL_DEVICES TRUE +diff -upr sysstat-10.1.5.orig/iostat.c sysstat-10.1.5/iostat.c +--- sysstat-10.1.5.orig/iostat.c 2013-03-23 17:31:46.000000000 +0100 ++++ sysstat-10.1.5/iostat.c 2016-04-29 15:02:24.264492629 +0200 +@@ -748,7 +748,8 @@ void read_diskstats_stat(int curr) + * (if different from "nodev") works around known issues + * with EMC PowerPath. + */ +- strncpy(dev_name, ioc_dname, MAX_NAME_LEN); ++ strncpy(dev_name, ioc_dname, MAX_NAME_LEN - 1); ++ dev_name[MAX_NAME_LEN - 1] = '\0'; + } + } + +@@ -759,7 +760,8 @@ void read_diskstats_stat(int curr) + */ + dm_name = transform_devmapname(major, minor); + if (dm_name) { +- strncpy(dev_name, dm_name, MAX_NAME_LEN); ++ strncpy(dev_name, dm_name, MAX_NAME_LEN - 1); ++ dev_name[MAX_NAME_LEN - 1] = '\0'; + } + } + diff --git a/SOURCES/sysstat-10.1.5-nfsiostat.patch b/SOURCES/sysstat-10.1.5-nfsiostat.patch new file mode 100644 index 0000000..9e4a382 --- /dev/null +++ b/SOURCES/sysstat-10.1.5-nfsiostat.patch @@ -0,0 +1,2119 @@ +diff -uprN sysstat-10.1.5.orig/configure sysstat-10.1.5/configure +--- sysstat-10.1.5.orig/configure 2013-03-13 15:28:25.000000000 +0100 ++++ sysstat-10.1.5/configure 2016-05-24 18:25:16.209668309 +0200 +@@ -5388,7 +5388,7 @@ ac_config_files="$ac_config_files man/io + # File must be renamed + ac_config_files="$ac_config_files man/cifsiostat.1:man/cifsiostat.in" + # File must be renamed +-ac_config_files="$ac_config_files man/nfsiostat.1:man/nfsiostat.in" ++ac_config_files="$ac_config_files man/nfsiostat-sysstat.1:man/nfsiostat-sysstat.in" + # File must be renamed + ac_config_files="$ac_config_files contrib/isag/isag" + # Permissions must be changed +@@ -6120,7 +6120,7 @@ do + "man/sysstat.5") CONFIG_FILES="$CONFIG_FILES man/sysstat.5:man/sysstat.in" ;; + "man/iostat.1") CONFIG_FILES="$CONFIG_FILES man/iostat.1:man/iostat.in" ;; + "man/cifsiostat.1") CONFIG_FILES="$CONFIG_FILES man/cifsiostat.1:man/cifsiostat.in" ;; +- "man/nfsiostat.1") CONFIG_FILES="$CONFIG_FILES man/nfsiostat.1:man/nfsiostat.in" ;; ++ "man/nfsiostat-sysstat.1") CONFIG_FILES="$CONFIG_FILES man/nfsiostat-sysstat.1:man/nfsiostat-sysstat.in" ;; + "contrib/isag/isag") CONFIG_FILES="$CONFIG_FILES contrib/isag/isag" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + +diff -uprN sysstat-10.1.5.orig/configure.in sysstat-10.1.5/configure.in +--- sysstat-10.1.5.orig/configure.in 2013-03-13 15:28:17.000000000 +0100 ++++ sysstat-10.1.5/configure.in 2016-05-24 18:25:16.209668309 +0200 +@@ -580,7 +580,7 @@ AC_CONFIG_FILES([man/sar.1:man/sar.in]) + AC_CONFIG_FILES([man/sysstat.5:man/sysstat.in]) # File must be renamed + AC_CONFIG_FILES([man/iostat.1:man/iostat.in]) # File must be renamed + AC_CONFIG_FILES([man/cifsiostat.1:man/cifsiostat.in]) # File must be renamed +-AC_CONFIG_FILES([man/nfsiostat.1:man/nfsiostat.in]) # File must be renamed ++AC_CONFIG_FILES([man/nfsiostat-sysstat.1:man/nfsiostat-sysstat.in]) # File must be renamed + AC_CONFIG_FILES([contrib/isag/isag], [chmod +x contrib/isag/isag]) # Permissions must be changed + + AC_OUTPUT(Makefile) +diff -uprN sysstat-10.1.5.orig/Makefile.in sysstat-10.1.5/Makefile.in +--- sysstat-10.1.5.orig/Makefile.in 2016-05-24 18:33:48.438839524 +0200 ++++ sysstat-10.1.5/Makefile.in 2016-05-24 18:25:16.209668309 +0200 +@@ -160,7 +160,7 @@ NLSPOT= $(NLSPO:.po=.pot) + % : %.o + $(CC) -o $@ $(CFLAGS) $^ $(LFLAGS) + +-all: sadc sar sadf iostat mpstat pidstat nfsiostat cifsiostat locales ++all: sadc sar sadf iostat mpstat pidstat nfsiostat-sysstat cifsiostat locales + + common.o: common.c version.h common.h ioconf.h sysconfig.h + +@@ -229,9 +229,9 @@ mpstat.o: mpstat.c mpstat.h version.h co + + mpstat: mpstat.o librdstats.a libsyscom.a + +-nfsiostat.o: nfsiostat.c nfsiostat.h version.h common.h ++nfsiostat-sysstat.o: nfsiostat-sysstat.c nfsiostat-sysstat.h version.h common.h + +-nfsiostat: nfsiostat.o librdstats.a libsyscom.a ++nfsiostat-sysstat: nfsiostat-sysstat.o librdstats.a libsyscom.a + + cifsiostat.o: cifsiostat.c cifsiostat.h version.h common.h + +@@ -273,8 +273,8 @@ ifeq ($(INSTALL_DOC),y) + $(INSTALL_DATA) $(MANGRPARG) man/mpstat.1 $(DESTDIR)$(MAN1_DIR) + rm -f $(DESTDIR)$(MAN1_DIR)/pidstat.1* + $(INSTALL_DATA) $(MANGRPARG) man/pidstat.1 $(DESTDIR)$(MAN1_DIR) +- rm -f $(DESTDIR)$(MAN1_DIR)/nfsiostat.1* +- $(INSTALL_DATA) $(MANGRPARG) man/nfsiostat.1 $(DESTDIR)$(MAN1_DIR) ++ rm -f $(DESTDIR)$(MAN1_DIR)/nfsiostat-sysstat.1* ++ $(INSTALL_DATA) $(MANGRPARG) man/nfsiostat-sysstat.1 $(DESTDIR)$(MAN1_DIR) + rm -f $(DESTDIR)$(MAN1_DIR)/cifsiostat.1* + $(INSTALL_DATA) $(MANGRPARG) man/cifsiostat.1 $(DESTDIR)$(MAN1_DIR) + ifeq ($(INSTALL_ISAG),y) +@@ -290,7 +290,7 @@ ifeq ($(COMPRESS_MANPG),y) + $(ZIP) $(DESTDIR)$(MAN1_DIR)/iostat.1 + $(ZIP) $(DESTDIR)$(MAN1_DIR)/mpstat.1 + $(ZIP) $(DESTDIR)$(MAN1_DIR)/pidstat.1 +- $(ZIP) $(DESTDIR)$(MAN1_DIR)/nfsiostat.1 ++ $(ZIP) $(DESTDIR)$(MAN1_DIR)/nfsiostat-sysstat.1 + $(ZIP) $(DESTDIR)$(MAN1_DIR)/cifsiostat.1 + ifeq ($(INSTALL_ISAG),y) + $(ZIP) $(DESTDIR)$(MAN1_DIR)/isag.1 +@@ -330,7 +330,7 @@ endif + $(INSTALL_BIN) iostat $(DESTDIR)$(BIN_DIR) + $(INSTALL_BIN) mpstat $(DESTDIR)$(BIN_DIR) + $(INSTALL_BIN) pidstat $(DESTDIR)$(BIN_DIR) +- $(INSTALL_BIN) nfsiostat $(DESTDIR)$(BIN_DIR) ++ $(INSTALL_BIN) nfsiostat-sysstat $(DESTDIR)$(BIN_DIR) + $(INSTALL_BIN) cifsiostat $(DESTDIR)$(BIN_DIR) + ifeq ($(INSTALL_ISAG),y) + $(INSTALL_BIN) contrib/isag/isag $(DESTDIR)$(BIN_DIR) +@@ -397,7 +397,7 @@ ifeq ($(INSTALL_DOC),y) + rm -f $(DESTDIR)$(MAN1_DIR)/iostat.1* + rm -f $(DESTDIR)$(MAN1_DIR)/mpstat.1* + rm -f $(DESTDIR)$(MAN1_DIR)/pidstat.1* +- rm -f $(DESTDIR)$(MAN1_DIR)/nfsiostat.1* ++ rm -f $(DESTDIR)$(MAN1_DIR)/nfsiostat-sysstat.1* + rm -f $(DESTDIR)$(MAN1_DIR)/cifsiostat.1* + ifeq ($(INSTALL_ISAG),y) + rm -f $(DESTDIR)$(MAN1_DIR)/isag.1 +@@ -425,7 +425,7 @@ uninstall_base: uninstall_man uninstall_ + rm -f $(DESTDIR)$(BIN_DIR)/iostat + rm -f $(DESTDIR)$(BIN_DIR)/mpstat + rm -f $(DESTDIR)$(BIN_DIR)/pidstat +- rm -f $(DESTDIR)$(BIN_DIR)/nfsiostat ++ rm -f $(DESTDIR)$(BIN_DIR)/nfsiostat-sysstat + rm -f $(DESTDIR)$(BIN_DIR)/cifsiostat + ifeq ($(INSTALL_ISAG),y) + rm -f $(DESTDIR)$(BIN_DIR)/isag +@@ -487,7 +487,7 @@ po-files: + endif + + clean: +- rm -f sadc sar sadf iostat mpstat pidstat nfsiostat cifsiostat *.o *.a core TAGS ++ rm -f sadc sar sadf iostat mpstat pidstat nfsiostat-sysstat cifsiostat *.o *.a core TAGS + find nls -name "*.gmo" -exec rm -f {} \; + + almost-distclean: clean nls/sysstat.pot +@@ -496,7 +496,7 @@ almost-distclean: clean nls/sysstat.pot + rm -f cron/sysstat.cron.hourly cron/sysstat.crond.sample cron/sysstat.crond.sample.in + rm -f contrib/isag/isag + rm -f man/sa1.8 man/sa2.8 man/sadc.8 man/sadf.1 man/sar.1 man/iostat.1 man/sysstat.5 +- rm -f man/cifsiostat.1 man/nfsiostat.1 ++ rm -f man/cifsiostat.1 man/nfsiostat-sysstat.1 + rm -f *.log config.status + rm -rf autom4te.cache + rm -f *.save *.old .*.swp data +diff -uprN sysstat-10.1.5.orig/man/nfsiostat.in sysstat-10.1.5/man/nfsiostat.in +--- sysstat-10.1.5.orig/man/nfsiostat.in 2012-07-13 08:48:55.000000000 +0200 ++++ sysstat-10.1.5/man/nfsiostat.in 1970-01-01 01:00:00.000000000 +0100 +@@ -1,175 +0,0 @@ +-.TH NFSIOSTAT 1 "JULY 2012" Linux "Linux User's Manual" -*- nroff -*- +-.SH NAME +-nfsiostat \- Report input/output statistics for network filesystems (NFS). +-.SH SYNOPSIS +-.ie 'yes'@WITH_DEBUG@' \{ +-.B nfsiostat [ -h ] [ -k | -m ] [ -t ] [ -V ] [ --debuginfo ] [ +-.I interval +-.B [ +-.I count +-.B ] ] +-.\} +-.el \{ +-.B nfsiostat [ -h ] [ -k | -m ] [ -t ] [ -V ] [ +-.I interval +-.B [ +-.I count +-.B ] ] +-.\} +-.SH DESCRIPTION +-The +-.B nfsiostat +-command displays statistics about read and write operations +-on NFS filesystems. +- +-The +-.I interval +-parameter specifies the amount of time in seconds between +-each report. The first report contains statistics for the time since +-system startup (boot). Each subsequent report contains statistics +-collected during the interval since the previous report. +-A report consists of an NFS header row followed by +-a line of statistics for each network filesystem that is mounted. +-The +-.I count +-parameter can be specified in conjunction with the +-.I interval +-parameter. If the +-.I count +-parameter is specified, the value of +-.I count +-determines the number of reports generated at +-.I interval +-seconds apart. If the +-.I interval +-parameter is specified without the +-.I count +-parameter, the +-.B nfsiostat +-command generates reports continuously. +- +-.SH REPORT +-The Network Filesystem (NFS) report provides statistics for each mounted network filesystem. +-Transfer rates are shown in 1K blocks by default, unless the environment +-variable POSIXLY_CORRECT is set, in which case 512-byte blocks are used. +-The report shows the following fields: +- +-.B Filesystem: +-.RS +-This columns shows the hostname of the NFS server followed by a colon and +-by the directory name where the network filesystem is mounted. +- +-.RE +-.B rBlk_nor/s (rkB_nor/s, rMB_nor) +-.RS +-Indicate the number of blocks (kilobytes, megabytes) read by applications +-via the read(2) system +-call interface. A block has a size of 512 bytes. +- +-.RE +-.B wBlk_nor/s (wkB_nor/s, wMB_nor/s) +-.RS +-Indicate the number of blocks (kilobytes, megabytes) written by applications +-via the write(2) system +-call interface. +- +-.RE +-.B rBlk_dir/s (rkB_dir/s, rMB_dir/s) +-.RS +-Indicate the number of blocks (kilobytes, megabytes) read from files +-opened with the O_DIRECT flag. +- +-.RE +-.B wBlk_dir/s (wkB_dir/s, wMB_dir/s) +-.RS +-Indicate the number of blocks (kilobytes, megabytes) written to files +-opened with the O_DIRECT flag. +- +-.RE +-.B rBlk_svr/s (rkB_svr/s, rMB_svr/s) +-.RS +-Indicate the number of blocks (kilobytes, megabytes) read from the server +-by the NFS client via an NFS READ request. +- +-.RE +-.B wBlk_svr/s (wkB_svr/s, wMB_svr/s) +-.RS +-Indicate the number of blocks (kilobytes, megabytes) written to the server +-by the NFS client via an NFS WRITE request. +- +-.RE +-.B ops/s +-.RS +-Indicate the number of operations that were issued to the filesystem per second. +- +-.RE +-.B rops/s +-.RS +-Indicate the number of 'read' operations that were issued to the filesystem +-per second. +- +-.RE +-.B wops/s +-.RS +-Indicate the number of 'write' operations that were issued to the filesystem +-per second. +-.RE +-.RE +-.SH OPTIONS +-.if 'yes'@WITH_DEBUG@' \{ +-.IP --debuginfo +-Print debug output to stderr. +-.\} +-.IP -h +-Make the NFS report easier to read by a human. +-.IP -k +-Display statistics in kilobytes per second. +-.IP -m +-Display statistics in megabytes per second. +-.IP -t +-Print the time for each report displayed. The timestamp format may depend +-on the value of the S_TIME_FORMAT environment variable (see below). +-.IP -V +-Print version number then exit. +- +-.SH ENVIRONMENT +-The +-.B nfsiostat +-command takes into account the following environment variables: +- +-.IP S_TIME_FORMAT +-If this variable exists and its value is +-.BR ISO +-then the current locale will be ignored when printing the date in the report +-header. The +-.B nfsiostat +-command will use the ISO 8601 format (YYYY-MM-DD) instead. +-The timestamp displayed with option -t will also be compliant with ISO 8601 +-format. +- +-.IP POSIXLY_CORRECT +-When this variable is set, transfer rates are shown in 512-byte blocks instead +-of the default 1K blocks. +- +-.SH BUG +-.I /proc +-filesystem must be mounted for +-.B nfsiostat +-to work. +- +-.SH FILE +-.I /proc/self/mountstats +-contains statistics for network filesystems. +-.SH AUTHORS +-Written by Ivana Varekova (varekova redhat.com) +- +-Maintained by Sebastien Godard (sysstat orange.fr) +-.SH SEE ALSO +-.BR sar (1), +-.BR pidstat (1), +-.BR mpstat (1), +-.BR vmstat (8), +-.BR iostat (1), +-.BR cifsiostat (1) +- +-.I http://pagesperso-orange.fr/sebastien.godard/ +diff -uprN sysstat-10.1.5.orig/man/nfsiostat-sysstat.in sysstat-10.1.5/man/nfsiostat-sysstat.in +--- sysstat-10.1.5.orig/man/nfsiostat-sysstat.in 1970-01-01 01:00:00.000000000 +0100 ++++ sysstat-10.1.5/man/nfsiostat-sysstat.in 2016-05-24 18:25:16.209668309 +0200 +@@ -0,0 +1,187 @@ ++.TH NFSIOSTAT-SYSSTAT 1 "JANUARY 2014" Linux "Linux User's Manual" -*- nroff -*- ++.SH NAME ++nfsiostat-sysstat (the nfsiostat command from the sysstat package) \- Report input/output statistics for network filesystems (NFS). ++.SH SYNOPSIS ++.ie 'yes'@WITH_DEBUG@' \{ ++.B nfsiostat-sysstat [ -h ] [ -k | -m ] [ -t ] [ -V ] [ --debuginfo ] [ ++.I interval ++.B [ ++.I count ++.B ] ] ++.\} ++.el \{ ++.B nfsiostat-sysstat [ -h ] [ -k | -m ] [ -t ] [ -V ] [ ++.I interval ++.B [ ++.I count ++.B ] ] ++.\} ++.SH DESCRIPTION ++The ++.B nfsiostat-sysstat ++command displays statistics about read and write operations ++on NFS filesystems. ++ ++The ++.I interval ++parameter specifies the amount of time in seconds between ++each report. The first report contains statistics for the time since ++system startup (boot). Each subsequent report contains statistics ++collected during the interval since the previous report. ++A report consists of an NFS header row followed by ++a line of statistics for each network filesystem that is mounted. ++The ++.I count ++parameter can be specified in conjunction with the ++.I interval ++parameter. If the ++.I count ++parameter is specified, the value of ++.I count ++determines the number of reports generated at ++.I interval ++seconds apart. If the ++.I interval ++parameter is specified without the ++.I count ++parameter, the ++.B nfsiostat-sysstat ++command generates reports continuously. ++ ++.SH REPORT ++The Network Filesystem (NFS) report provides statistics for each mounted network filesystem. ++Transfer rates are shown in 1K blocks by default, unless the environment ++variable POSIXLY_CORRECT is set, in which case 512-byte blocks are used. ++The report shows the following fields: ++ ++.B Filesystem: ++.RS ++This columns shows the hostname of the NFS server followed by a colon and ++by the directory name where the network filesystem is mounted. ++ ++.RE ++.B rBlk_nor/s (rkB_nor/s, rMB_nor) ++.RS ++Indicate the number of blocks (kilobytes, megabytes) read by applications ++via the read(2) system ++call interface. A block has a size of 512 bytes. ++ ++.RE ++.B wBlk_nor/s (wkB_nor/s, wMB_nor/s) ++.RS ++Indicate the number of blocks (kilobytes, megabytes) written by applications ++via the write(2) system ++call interface. ++ ++.RE ++.B rBlk_dir/s (rkB_dir/s, rMB_dir/s) ++.RS ++Indicate the number of blocks (kilobytes, megabytes) read from files ++opened with the O_DIRECT flag. ++ ++.RE ++.B wBlk_dir/s (wkB_dir/s, wMB_dir/s) ++.RS ++Indicate the number of blocks (kilobytes, megabytes) written to files ++opened with the O_DIRECT flag. ++ ++.RE ++.B rBlk_svr/s (rkB_svr/s, rMB_svr/s) ++.RS ++Indicate the number of blocks (kilobytes, megabytes) read from the server ++by the NFS client via an NFS READ request. ++ ++.RE ++.B wBlk_svr/s (wkB_svr/s, wMB_svr/s) ++.RS ++Indicate the number of blocks (kilobytes, megabytes) written to the server ++by the NFS client via an NFS WRITE request. ++ ++.RE ++.B ops/s ++.RS ++Indicate the number of operations that were issued to the filesystem per second. ++ ++.RE ++.B rops/s ++.RS ++Indicate the number of 'read' operations that were issued to the filesystem ++per second. ++ ++.RE ++.B wops/s ++.RS ++Indicate the number of 'write' operations that were issued to the filesystem ++per second. ++.RE ++.RE ++.SH OPTIONS ++.if 'yes'@WITH_DEBUG@' \{ ++.IP --debuginfo ++Print debug output to stderr. ++.\} ++.IP -h ++Make the NFS report easier to read by a human. ++.IP -k ++Display statistics in kilobytes per second. ++.IP -m ++Display statistics in megabytes per second. ++.IP -t ++Print the time for each report displayed. The timestamp format may depend ++on the value of the S_TIME_FORMAT environment variable (see below). ++.IP -V ++Print version number then exit. ++ ++.SH ENVIRONMENT ++The ++.B nfsiostat-sysstat ++command takes into account the following environment variables: ++ ++.IP S_TIME_FORMAT ++If this variable exists and its value is ++.BR ISO ++then the current locale will be ignored when printing the date in the report ++header. The ++.B nfsiostat-sysstat ++command will use the ISO 8601 format (YYYY-MM-DD) instead. ++The timestamp displayed with option -t will also be compliant with ISO 8601 ++format. ++ ++.IP POSIXLY_CORRECT ++When this variable is set, transfer rates are shown in 512-byte blocks instead ++of the default 1K blocks. ++ ++.SH BUG ++.I /proc ++filesystem must be mounted for ++.B nfsiostat-sysstat ++to work. ++ ++.SH FILE ++.I /proc/self/mountstats ++contains statistics for network filesystems. ++ ++.SH WARNING ++The nfsiostat ++command from the sysstat package (nfsiostat-sysstat) is now obsolete and is no longer maintained. ++It will be removed in a future sysstat version. ++Please use now the ++.B nfsiostat ++command from the ++.I nfs-utils ++package. ++ ++.SH AUTHORS ++Written by Ivana Varekova (varekova redhat.com) ++ ++Maintained by Sebastien Godard (sysstat orange.fr) ++.SH SEE ALSO ++.BR nfsiostat (8), ++.BR sar (1), ++.BR pidstat (1), ++.BR mpstat (1), ++.BR vmstat (8), ++.BR iostat (1), ++.BR cifsiostat (1) ++ ++.I http://pagesperso-orange.fr/sebastien.godard/ +diff -uprN sysstat-10.1.5.orig/nfsiostat.c sysstat-10.1.5/nfsiostat.c +--- sysstat-10.1.5.orig/nfsiostat.c 2016-05-24 18:33:48.444839516 +0200 ++++ sysstat-10.1.5/nfsiostat.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,747 +0,0 @@ +-/* +- * nfsiostat: Report NFS I/O statistics +- * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved +- * Written by Ivana Varekova +- * +- *************************************************************************** +- * This program is free software; you can redistribute it and/or modify it * +- * under the terms of the GNU General Public License as published by the * +- * Free Software Foundation; either version 2 of the License, or (at your * +- * option) any later version. * +- * * +- * This program is distributed in the hope that it will be useful, but * +- * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY * +- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * +- * for more details. * +- * * +- * You should have received a copy of the GNU General Public License along * +- * with this program; if not, write to the Free Software Foundation, Inc., * +- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * +- *************************************************************************** +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "version.h" +-#include "nfsiostat.h" +-#include "common.h" +- +-#ifdef USE_NLS +-#include +-#include +-#define _(string) gettext(string) +-#else +-#define _(string) (string) +-#endif +- +-#define SCCSID "@(#)sysstat-" VERSION ": " __FILE__ " compiled " __DATE__ " " __TIME__ +-char *sccsid(void) { return (SCCSID); } +- +-unsigned long long uptime0[2] = {0, 0}; +-struct io_nfs_stats *st_ionfs[2]; +-struct io_hdr_stats *st_hdr_ionfs; +- +-int ionfs_nr = 0; /* Nb of NFS mounted directories found */ +-int cpu_nr = 0; /* Nb of processors on the machine */ +-int flags = 0; /* Flag for common options and system state */ +- +-long interval = 0; +-char timestamp[64]; +- +-struct sigaction alrm_act; +- +-/* +- *************************************************************************** +- * Print usage and exit. +- * +- * IN: +- * @progname Name of sysstat command. +- *************************************************************************** +- */ +-void usage(char *progname) +-{ +- fprintf(stderr, _("Usage: %s [ options ] [ [ ] ]\n"), +- progname); +- +-#ifdef DEBUG +- fprintf(stderr, _("Options are:\n" +- "[ -h ] [ -k | -m ] [ -t ] [ -V ] [ --debuginfo ]\n")); +-#else +- fprintf(stderr, _("Options are:\n" +- "[ -h ] [ -k | -m ] [ -t ] [ -V ]\n")); +-#endif +- exit(1); +-} +- +-/* +- *************************************************************************** +- * Set output unit. Unit will be kB/s unless POSIXLY_CORRECT +- * environment variable has been set, in which case the output will be +- * expressed in blocks/s. +- *************************************************************************** +- */ +-void set_output_unit(void) +-{ +- char *e; +- +- if (DISPLAY_KILOBYTES(flags) || DISPLAY_MEGABYTES(flags)) +- return; +- +- /* Check POSIXLY_CORRECT environment variable */ +- if ((e = getenv(ENV_POSIXLY_CORRECT)) == NULL) { +- /* Variable not set: Unit is kB/s and not blocks/s */ +- flags |= I_D_KILOBYTES; +- } +-} +- +-/* +- *************************************************************************** +- * SIGALRM signal handler. +- * +- * IN: +- * @sig Signal number. +- *************************************************************************** +- */ +-void alarm_handler(int sig) +-{ +- alarm(interval); +-} +- +-/* +- *************************************************************************** +- * Find number of NFS-mounted points that are registered in +- * /proc/self/mountstats. +- * +- * RETURNS: +- * Number of NFS-mounted points. +- *************************************************************************** +- */ +-int get_nfs_mount_nr(void) +-{ +- FILE *fp; +- char line[8192]; +- char type_name[10]; +- unsigned int nfs = 0; +- +- if ((fp = fopen(NFSMOUNTSTATS, "r")) == NULL) +- /* File non-existent */ +- return 0; +- +- while (fgets(line, 8192, fp) != NULL) { +- +- if ((strstr(line, "mounted")) && (strstr(line, "on")) && +- (strstr(line, "with")) && (strstr(line, "fstype"))) { +- +- sscanf(strstr(line, "fstype") + 6, "%9s", type_name); +- if ((!strncmp(type_name, "nfs", 3)) && (strncmp(type_name, "nfsd", 4))) { +- nfs ++; +- } +- } +- } +- +- fclose(fp); +- +- return nfs; +-} +- +-/* +- *************************************************************************** +- * Set every nfs_io entry to inactive state (unregistered). +- *************************************************************************** +- */ +-void set_entries_inactive(void) +-{ +- int i; +- struct io_hdr_stats *shi = st_hdr_ionfs; +- +- for (i = 0; i < ionfs_nr; i++, shi++) { +- shi->active = FALSE; +- } +-} +- +-/* +- *************************************************************************** +- * Free inactive entries (mark them as unused). +- *************************************************************************** +- */ +-void free_inactive_entries(void) +-{ +- int i; +- struct io_hdr_stats *shi = st_hdr_ionfs; +- +- for (i = 0; i < ionfs_nr; i++, shi++) { +- if (!shi->active) { +- shi->used = FALSE; +- } +- } +-} +- +-/* +- *************************************************************************** +- * Allocate and init structures, according to system state. +- *************************************************************************** +- */ +-void io_sys_init(void) +-{ +- int i; +- +- /* How many processors on this machine? */ +- cpu_nr = get_cpu_nr(~0); +- +- /* Get number of NFS directories in /proc/self/mountstats */ +- if ((ionfs_nr = get_nfs_mount_nr()) > 0) { +- ionfs_nr += NR_NFS_PREALLOC; +- } +- if ((st_hdr_ionfs = (struct io_hdr_stats *) calloc(ionfs_nr, IO_HDR_STATS_SIZE)) == NULL) { +- perror("malloc"); +- exit(4); +- } +- +- /* Allocate structures for number of NFS directories found */ +- for (i = 0; i < 2; i++) { +- if ((st_ionfs[i] = +- (struct io_nfs_stats *) calloc(ionfs_nr, IO_NFS_STATS_SIZE)) == NULL) { +- perror("malloc"); +- exit(4); +- } +- } +-} +- +-/* +- *************************************************************************** +- * Free various structures. +- *************************************************************************** +-*/ +-void io_sys_free(void) +-{ +- int i; +- +- /* Free I/O NFS directories structures */ +- for (i = 0; i < 2; i++) { +- +- if (st_ionfs[i]) { +- free(st_ionfs[i]); +- } +- } +- +- if (st_hdr_ionfs) { +- free(st_hdr_ionfs); +- } +-} +- +-/* +- *************************************************************************** +- * Save stats for current NFS filesystem. +- * +- * IN: +- * @name Name of NFS filesystem. +- * @curr Index in array for current sample statistics. +- * @st_io Structure with NFS statistics to save. +- * @ionfs_nr Number of NFS filesystems. +- * @st_hdr_ionfs Pointer on structures describing an NFS filesystem. +- * +- * OUT: +- * @st_hdr_ionfs Pointer on structures describing an NFS filesystem. +- *************************************************************************** +- */ +-void save_stats(char *name, int curr, void *st_io) +-{ +- int i, j; +- struct io_hdr_stats *st_hdr_ionfs_i; +- struct io_nfs_stats *st_ionfs_i; +- +- /* Look for NFS directory in data table */ +- for (i = 0; i < ionfs_nr; i++) { +- st_hdr_ionfs_i = st_hdr_ionfs + i; +- if ((st_hdr_ionfs_i->used) && +- (!strcmp(st_hdr_ionfs_i->name, name))) { +- break; +- } +- } +- +- if (i == ionfs_nr) { +- /* +- * This is a new filesystem: Look for an unused entry to store it. +- */ +- for (i = 0; i < ionfs_nr; i++) { +- st_hdr_ionfs_i = st_hdr_ionfs + i; +- if (!st_hdr_ionfs_i->used) { +- /* Unused entry found... */ +- st_hdr_ionfs_i->used = TRUE; /* Indicate it is now used */ +- st_hdr_ionfs_i->active = TRUE; +- +- strcpy(st_hdr_ionfs_i->name, name); +- st_ionfs_i = st_ionfs[curr] + i; +- memset(st_ionfs_i, 0, IO_NFS_STATS_SIZE); +- *st_ionfs_i = *((struct io_nfs_stats *) st_io); +- break; +- } +- } +- if (i == ionfs_nr) { +- /* All entries are used: The number has to be increased */ +- ionfs_nr = ionfs_nr + 5; +- +- /* Increase the size of st_hdr_ionfs buffer */ +- if ((st_hdr_ionfs = (struct io_hdr_stats *) +- realloc(st_hdr_ionfs, ionfs_nr * IO_HDR_STATS_SIZE)) == NULL) { +- perror("malloc"); +- exit(4); +- } +- +- /* Set the new entries inactive */ +- for (j = 0; j < 5; j++) { +- st_hdr_ionfs_i = st_hdr_ionfs + i + j; +- st_hdr_ionfs_i->used = FALSE; +- st_hdr_ionfs_i->active = FALSE; +- } +- +- /* Increase the size of st_hdr_ionfs buffer */ +- for (j = 0; j < 2; j++) { +- if ((st_ionfs[j] = (struct io_nfs_stats *) +- realloc(st_ionfs[j], ionfs_nr * IO_NFS_STATS_SIZE)) == NULL) { +- perror("malloc"); +- exit(4); +- } +- memset(st_ionfs[j] + i, 0, 5 * IO_NFS_STATS_SIZE); +- } +- +- /* Now i shows the first unused entry of the new block */ +- st_hdr_ionfs_i = st_hdr_ionfs + i; +- st_hdr_ionfs_i->used = TRUE; /* Indicate it is now used */ +- strcpy(st_hdr_ionfs_i->name, name); +- st_ionfs_i = st_ionfs[curr] + i; +- memset(st_ionfs_i, 0, IO_NFS_STATS_SIZE); +- } +- } else { +- st_hdr_ionfs_i = st_hdr_ionfs + i; +- st_hdr_ionfs_i->used = TRUE; +- st_hdr_ionfs_i->active = TRUE; +- st_ionfs_i = st_ionfs[curr] + i; +- *st_ionfs_i = *((struct io_nfs_stats *) st_io); +- } +- /* +- * else it was a new NFS directory +- * but there was no free structure to store it. +- */ +-} +- +-/* +- *************************************************************************** +- * Read NFS-mount directories stats from /proc/self/mountstats. +- * +- * IN: +- * @curr Index in array for current sample statistics. +- *************************************************************************** +- */ +-void read_nfs_stat(int curr) +-{ +- FILE *fp; +- int sw = 0; +- char line[256]; +- char *xprt_line; +- char *mount_part; +- char nfs_name[MAX_NAME_LEN]; +- char mount[10], on[10], prefix[10], aux[32]; +- char operation[16]; +- struct io_nfs_stats snfs; +- long int v1; +- +- /* Every I/O NFS entry is potentially unregistered */ +- set_entries_inactive(); +- +- if ((fp = fopen(NFSMOUNTSTATS, "r")) == NULL) +- return; +- +- sprintf(aux, "%%%ds", +- MAX_NAME_LEN < 200 ? MAX_NAME_LEN-1 : 200); +- +- while (fgets(line, 256, fp) != NULL) { +- /* Read NFS directory name */ +- if (!strncmp(line, "device", 6)) { +- sw = 0; +- sscanf(line + 6, aux, nfs_name); +- mount_part = strchr(line + 7, ' '); +- if (mount_part != NULL) { +- sscanf(mount_part, "%9s %9s", mount, on); +- if ((!strncmp(mount, "mounted", 7)) && (!strncmp(on, "on", 2))) { +- sw = 1; +- } +- } +- } +- +- sscanf(line, "%9s", prefix); +- if (sw && (!strncmp(prefix, "bytes:", 6))) { +- /* Read the stats for the last NFS-mounted directory */ +- sscanf(strstr(line, "bytes:") + 6, "%llu %llu %llu %llu %llu %llu", +- &snfs.rd_normal_bytes, &snfs.wr_normal_bytes, +- &snfs.rd_direct_bytes, &snfs.wr_direct_bytes, +- &snfs.rd_server_bytes, &snfs.wr_server_bytes); +- sw = 2; +- } +- +- if ((sw == 2) && (!strncmp(prefix, "xprt:", 5))) { +- /* +- * Read extended statistic for the last NFS-mounted directory +- * - number of sent rpc requests. +- */ +- xprt_line = (strstr(line, "xprt:") + 6); +- /* udp, tcp or rdma data */ +- if (!strncmp(xprt_line, "udp", 3)) { +- /* port bind_count sends recvs (bad_xids req_u bklog_u) */ +- sscanf(strstr(xprt_line, "udp") + 4, "%*u %*u %lu", +- &snfs.rpc_sends); +- } +- if (!strncmp(xprt_line, "tcp", 3)) { +- /* +- * port bind_counter connect_count connect_time idle_time +- * sends recvs (bad_xids req_u bklog_u) +- */ +- sscanf(strstr(xprt_line, "tcp") + 4, +- "%*u %*u %*u %*u %*d %lu", +- &snfs.rpc_sends); +- } +- if (!strncmp(xprt_line,"rdma", 4)) { +- /* +- * 0(port) bind_count connect_count connect_time idle_time +- * sends recvs (bad_xids req_u bklog_u...) +- */ +- sscanf(strstr(xprt_line, "rdma") + 5, +- "%*u %*u %*u %*u %*d %lu", +- &snfs.rpc_sends); +- } +- sw = 3; +- } +- +- if ((sw == 3) && (!strncmp(prefix, "per-op", 6))) { +- sw = 4; +- while (sw == 4) { +- fgets(line, 256, fp); +- sscanf(line, "%15s %lu", operation, &v1); +- if (!strncmp(operation, "READ:", 5)) { +- snfs.nfs_rops = v1; +- } +- else if (!strncmp(operation, "WRITE:", 6)) { +- snfs.nfs_wops = v1; +- +- save_stats(nfs_name, curr, &snfs); +- sw = 0; +- } +- } +- } +- } +- +- fclose(fp); +- +- /* Free structures corresponding to unregistered filesystems */ +- free_inactive_entries(); +-} +- +-/* +- *************************************************************************** +- * Display NFS stats header. +- * +- * OUT: +- * @fctr Conversion factor. +- *************************************************************************** +- */ +-void write_nfs_stat_header(int *fctr) +-{ +- printf("Filesystem: "); +- if (DISPLAY_KILOBYTES(flags)) { +- printf(" rkB_nor/s wkB_nor/s rkB_dir/s wkB_dir/s" +- " rkB_svr/s wkB_svr/s"); +- *fctr = 1024; +- } +- else if (DISPLAY_MEGABYTES(flags)) { +- printf(" rMB_nor/s wMB_nor/s rMB_dir/s wMB_dir/s" +- " rMB_svr/s wMB_svr/s"); +- *fctr = 1024 * 1024; +- } +- else { +- printf(" rBlk_nor/s wBlk_nor/s rBlk_dir/s wBlk_dir/s" +- " rBlk_svr/s wBlk_svr/s"); +- *fctr = 512; +- } +- printf(" ops/s rops/s wops/s\n"); +-} +- +-/* +- *************************************************************************** +- * Write NFS stats read from /proc/self/mountstats. +- * +- * IN: +- * @curr Index in array for current sample statistics. +- * @itv Interval of time. +- * @fctr Conversion factor. +- * @shi Structures describing the NFS filesystems. +- * @ioi Current sample statistics. +- * @ioj Previous sample statistics. +- *************************************************************************** +- */ +-void write_nfs_stat(int curr, unsigned long long itv, int fctr, +- struct io_hdr_stats *shi, struct io_nfs_stats *ioni, +- struct io_nfs_stats *ionj) +-{ +- if (DISPLAY_HUMAN_READ(flags)) { +- printf("%-22s\n%23s", shi->name, ""); +- } +- else { +- printf("%-22s ", shi->name); +- } +- printf("%12.2f %12.2f %12.2f %12.2f %12.2f %12.2f %9.2f %9.2f %9.2f\n", +- S_VALUE(ionj->rd_normal_bytes, ioni->rd_normal_bytes, itv) / fctr, +- S_VALUE(ionj->wr_normal_bytes, ioni->wr_normal_bytes, itv) / fctr, +- S_VALUE(ionj->rd_direct_bytes, ioni->rd_direct_bytes, itv) / fctr, +- S_VALUE(ionj->wr_direct_bytes, ioni->wr_direct_bytes, itv) / fctr, +- S_VALUE(ionj->rd_server_bytes, ioni->rd_server_bytes, itv) / fctr, +- S_VALUE(ionj->wr_server_bytes, ioni->wr_server_bytes, itv) / fctr, +- S_VALUE(ionj->rpc_sends, ioni->rpc_sends, itv), +- S_VALUE(ionj->nfs_rops, ioni->nfs_rops, itv), +- S_VALUE(ionj->nfs_wops, ioni->nfs_wops, itv)); +-} +- +-/* +- *************************************************************************** +- * Print everything now (stats and uptime). +- * +- * IN: +- * @curr Index in array for current sample statistics. +- * @rectime Current date and time. +- *************************************************************************** +- */ +-void write_stats(int curr, struct tm *rectime) +-{ +- int i, fctr = 1; +- unsigned long long itv; +- struct io_hdr_stats *shi; +- struct io_nfs_stats *ioni, *ionj; +- +- /* Test stdout */ +- TEST_STDOUT(STDOUT_FILENO); +- +- /* Print time stamp */ +- if (DISPLAY_TIMESTAMP(flags)) { +- if (DISPLAY_ISO(flags)) { +- strftime(timestamp, sizeof(timestamp), "%FT%T%z", rectime); +- } +- else { +- strftime(timestamp, sizeof(timestamp), "%x %X", rectime); +- } +- printf("%s\n", timestamp); +-#ifdef DEBUG +- if (DISPLAY_DEBUG(flags)) { +- fprintf(stderr, "%s\n", timestamp); +- } +-#endif +- } +- +- /* Interval of time, reduced to one processor */ +- itv = get_interval(uptime0[!curr], uptime0[curr]); +- +- shi = st_hdr_ionfs; +- +- /* Display NFS stats header */ +- write_nfs_stat_header(&fctr); +- +- for (i = 0; i < ionfs_nr; i++, shi++) { +- if (shi->used) { +- ioni = st_ionfs[curr] + i; +- ionj = st_ionfs[!curr] + i; +-#ifdef DEBUG +- if (DISPLAY_DEBUG(flags)) { +- /* Debug output */ +- fprintf(stderr, "name=%s itv=%llu fctr=%d ioni{ rd_normal_bytes=%llu " +- "wr_normal_bytes=%llu rd_direct_bytes=%llu wr_direct_bytes=%llu rd_server_bytes=%llu " +- "wr_server_bytes=%llu rpc_sends=%lu nfs_rops=%lu nfs_wops=%lu }\n", +- shi->name, itv, fctr, +- ioni->rd_normal_bytes, ioni->wr_normal_bytes, +- ioni->rd_direct_bytes, ioni->wr_direct_bytes, +- ioni->rd_server_bytes, ioni->wr_server_bytes, +- ioni->rpc_sends, +- ioni->nfs_rops, ioni->nfs_wops); +- } +-#endif +- write_nfs_stat(curr, itv, fctr, shi, ioni, ionj); +- } +- } +- printf("\n"); +-} +- +-/* +- *************************************************************************** +- * Main loop: Read stats from the relevant sources and display them. +- * +- * IN: +- * @count Number of lines of stats to print. +- * @rectime Current date and time. +- *************************************************************************** +- */ +-void rw_io_stat_loop(long int count, struct tm *rectime) +-{ +- int curr = 1; +- +- /* Don't buffer data if redirected to a pipe */ +- setbuf(stdout, NULL); +- +- do { +- /* Read system uptime (reduced to one processor) */ +- uptime0[curr] = 0; +- read_uptime(&(uptime0[curr])); +- if (!uptime0[curr]) +- /* Cannot read system uptime (/proc/uptime doesn't exist) */ +- exit(2); +- +- /* Read NFS directories stats */ +- read_nfs_stat(curr); +- +- /* Get time */ +- get_localtime(rectime, 0); +- +- /* Print results */ +- write_stats(curr, rectime); +- +- if (count > 0) { +- count--; +- } +- if (count) { +- curr ^= 1; +- pause(); +- } +- } +- while (count); +-} +- +-/* +- *************************************************************************** +- * Main entry to the nfsiostat program. +- *************************************************************************** +- */ +-int main(int argc, char **argv) +-{ +- int it = 0; +- int opt = 1; +- int i; +- long count = 1; +- struct utsname header; +- struct tm rectime; +- +-#ifdef USE_NLS +- /* Init National Language Support */ +- init_nls(); +-#endif +- +- /* Get HZ */ +- get_HZ(); +- +- /* Process args... */ +- while (opt < argc) { +- +-#ifdef DEBUG +- if (!strcmp(argv[opt], "--debuginfo")) { +- flags |= I_D_DEBUG; +- opt++; +- } else +-#endif +- if (!strncmp(argv[opt], "-", 1)) { +- for (i = 1; *(argv[opt] + i); i++) { +- +- switch (*(argv[opt] + i)) { +- +- case 'h': +- /* Display an easy-to-read NFS report */ +- flags |= I_D_HUMAN_READ; +- break; +- +- case 'k': +- if (DISPLAY_MEGABYTES(flags)) { +- usage(argv[0]); +- } +- /* Display stats in kB/s */ +- flags |= I_D_KILOBYTES; +- break; +- +- case 'm': +- if (DISPLAY_KILOBYTES(flags)) { +- usage(argv[0]); +- } +- /* Display stats in MB/s */ +- flags |= I_D_MEGABYTES; +- break; +- +- case 't': +- /* Display timestamp */ +- flags |= I_D_TIMESTAMP; +- break; +- +- case 'V': +- /* Print version number and exit */ +- print_version(); +- break; +- +- default: +- usage(argv[0]); +- } +- } +- opt++; +- } +- +- else if (!it) { +- interval = atol(argv[opt++]); +- if (interval < 0) { +- usage(argv[0]); +- } +- count = -1; +- it = 1; +- } +- +- else if (it > 0) { +- count = atol(argv[opt++]); +- if ((count < 1) || !interval) { +- usage(argv[0]); +- } +- it = -1; +- } +- else { +- usage(argv[0]); +- } +- } +- +- if (!interval) { +- count = 1; +- } +- +- /* Select output unit (kB/s or blocks/s) */ +- set_output_unit(); +- +- /* Init structures according to machine architecture */ +- io_sys_init(); +- +- get_localtime(&rectime, 0); +- +- /* Get system name, release number and hostname */ +- uname(&header); +- if (print_gal_header(&rectime, header.sysname, header.release, +- header.nodename, header.machine, cpu_nr)) { +- flags |= I_D_ISO; +- } +- printf("\n"); +- +- /* Set a handler for SIGALRM */ +- memset(&alrm_act, 0, sizeof(alrm_act)); +- alrm_act.sa_handler = (void *) alarm_handler; +- sigaction(SIGALRM, &alrm_act, NULL); +- alarm(interval); +- +- /* Main loop */ +- rw_io_stat_loop(count, &rectime); +- +- /* Free structures */ +- io_sys_free(); +- +- return 0; +-} +diff -uprN sysstat-10.1.5.orig/nfsiostat.h sysstat-10.1.5/nfsiostat.h +--- sysstat-10.1.5.orig/nfsiostat.h 2013-03-23 17:31:46.000000000 +0100 ++++ sysstat-10.1.5/nfsiostat.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,57 +0,0 @@ +-/* +- * nfsiostat: Report NFS I/O statistics +- * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved +- * Written by Ivana Varekova +- */ +- +-#ifndef _NFSIOSTAT_H +-#define _NFSIOSTAT_H +- +-#include "common.h" +- +-#define NFSMOUNTSTATS "/proc/self/mountstats" +- +-/* I_: iostat - D_: Display - F_: Flag */ +-#define I_D_TIMESTAMP 0x001 +-#define I_D_KILOBYTES 0x002 +-#define I_D_MEGABYTES 0x004 +-#define I_D_ISO 0x008 +-#define I_D_HUMAN_READ 0x010 +-#define I_D_DEBUG 0x020 +- +-#define DISPLAY_TIMESTAMP(m) (((m) & I_D_TIMESTAMP) == I_D_TIMESTAMP) +-#define DISPLAY_KILOBYTES(m) (((m) & I_D_KILOBYTES) == I_D_KILOBYTES) +-#define DISPLAY_MEGABYTES(m) (((m) & I_D_MEGABYTES) == I_D_MEGABYTES) +-#define DISPLAY_ISO(m) (((m) & I_D_ISO) == I_D_ISO) +-#define DISPLAY_HUMAN_READ(m) (((m) & I_D_HUMAN_READ) == I_D_HUMAN_READ) +-#define DISPLAY_DEBUG(m) (((m) & I_D_DEBUG) == I_D_DEBUG) +- +-/* Environment variable */ +-#define ENV_POSIXLY_CORRECT "POSIXLY_CORRECT" +- +-/* Preallocation constats */ +-#define NR_NFS_PREALLOC 2 +- +-struct io_nfs_stats { +- unsigned long long rd_normal_bytes __attribute__ ((aligned (8))); +- unsigned long long wr_normal_bytes __attribute__ ((packed)); +- unsigned long long rd_direct_bytes __attribute__ ((packed)); +- unsigned long long wr_direct_bytes __attribute__ ((packed)); +- unsigned long long rd_server_bytes __attribute__ ((packed)); +- unsigned long long wr_server_bytes __attribute__ ((packed)); +- unsigned long rpc_sends __attribute__ ((packed)); +- unsigned long nfs_rops __attribute__ ((packed)); +- unsigned long nfs_wops __attribute__ ((packed)); +-}; +- +-#define IO_NFS_STATS_SIZE (sizeof(struct io_nfs_stats)) +- +-struct io_hdr_stats { +- unsigned int active __attribute__ ((aligned (4))); +- unsigned int used __attribute__ ((packed)); +- char name[MAX_NAME_LEN]; +-}; +- +-#define IO_HDR_STATS_SIZE (sizeof(struct io_hdr_stats)) +- +-#endif /* _NFSIOSTAT_H */ +diff -uprN sysstat-10.1.5.orig/nfsiostat-sysstat.c sysstat-10.1.5/nfsiostat-sysstat.c +--- sysstat-10.1.5.orig/nfsiostat-sysstat.c 1970-01-01 01:00:00.000000000 +0100 ++++ sysstat-10.1.5/nfsiostat-sysstat.c 2016-05-24 18:30:06.285162523 +0200 +@@ -0,0 +1,750 @@ ++/* ++ * nfsiostat-sysstat: Report NFS I/O statistics ++ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved ++ * Written by Ivana Varekova ++ * ++ *************************************************************************** ++ * This program is free software; you can redistribute it and/or modify it * ++ * under the terms of the GNU General Public License as published by the * ++ * Free Software Foundation; either version 2 of the License, or (at your * ++ * option) any later version. * ++ * * ++ * This program is distributed in the hope that it will be useful, but * ++ * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY * ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * ++ * for more details. * ++ * * ++ * You should have received a copy of the GNU General Public License along * ++ * with this program; if not, write to the Free Software Foundation, Inc., * ++ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ++ *************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "version.h" ++#include "nfsiostat-sysstat.h" ++#include "common.h" ++ ++#ifdef USE_NLS ++#include ++#include ++#define _(string) gettext(string) ++#else ++#define _(string) (string) ++#endif ++ ++#define SCCSID "@(#)sysstat-" VERSION ": " __FILE__ " compiled " __DATE__ " " __TIME__ ++char *sccsid(void) { return (SCCSID); } ++ ++unsigned long long uptime0[2] = {0, 0}; ++struct io_nfs_stats *st_ionfs[2]; ++struct io_hdr_stats *st_hdr_ionfs; ++ ++int ionfs_nr = 0; /* Nb of NFS mounted directories found */ ++int cpu_nr = 0; /* Nb of processors on the machine */ ++int flags = 0; /* Flag for common options and system state */ ++ ++long interval = 0; ++char timestamp[64]; ++ ++struct sigaction alrm_act; ++ ++/* ++ *************************************************************************** ++ * Print usage and exit. ++ * ++ * IN: ++ * @progname Name of sysstat command. ++ *************************************************************************** ++ */ ++void usage(char *progname) ++{ ++ fprintf(stderr, _("Usage: %s [ options ] [ [ ] ]\n"), ++ progname); ++ ++#ifdef DEBUG ++ fprintf(stderr, _("Options are:\n" ++ "[ -h ] [ -k | -m ] [ -t ] [ -V ] [ --debuginfo ]\n")); ++#else ++ fprintf(stderr, _("Options are:\n" ++ "[ -h ] [ -k | -m ] [ -t ] [ -V ]\n")); ++#endif ++ exit(1); ++} ++ ++/* ++ *************************************************************************** ++ * Set output unit. Unit will be kB/s unless POSIXLY_CORRECT ++ * environment variable has been set, in which case the output will be ++ * expressed in blocks/s. ++ *************************************************************************** ++ */ ++void set_output_unit(void) ++{ ++ char *e; ++ ++ if (DISPLAY_KILOBYTES(flags) || DISPLAY_MEGABYTES(flags)) ++ return; ++ ++ /* Check POSIXLY_CORRECT environment variable */ ++ if ((e = getenv(ENV_POSIXLY_CORRECT)) == NULL) { ++ /* Variable not set: Unit is kB/s and not blocks/s */ ++ flags |= I_D_KILOBYTES; ++ } ++} ++ ++/* ++ *************************************************************************** ++ * SIGALRM signal handler. ++ * ++ * IN: ++ * @sig Signal number. ++ *************************************************************************** ++ */ ++void alarm_handler(int sig) ++{ ++ alarm(interval); ++} ++ ++/* ++ *************************************************************************** ++ * Find number of NFS-mounted points that are registered in ++ * /proc/self/mountstats. ++ * ++ * RETURNS: ++ * Number of NFS-mounted points. ++ *************************************************************************** ++ */ ++int get_nfs_mount_nr(void) ++{ ++ FILE *fp; ++ char line[8192]; ++ char type_name[10]; ++ unsigned int nfs = 0; ++ ++ if ((fp = fopen(NFSMOUNTSTATS, "r")) == NULL) ++ /* File non-existent */ ++ return 0; ++ ++ while (fgets(line, 8192, fp) != NULL) { ++ ++ if ((strstr(line, "mounted")) && (strstr(line, "on")) && ++ (strstr(line, "with")) && (strstr(line, "fstype"))) { ++ ++ sscanf(strstr(line, "fstype") + 6, "%9s", type_name); ++ if ((!strncmp(type_name, "nfs", 3)) && (strncmp(type_name, "nfsd", 4))) { ++ nfs ++; ++ } ++ } ++ } ++ ++ fclose(fp); ++ ++ return nfs; ++} ++ ++/* ++ *************************************************************************** ++ * Set every nfs_io entry to inactive state (unregistered). ++ *************************************************************************** ++ */ ++void set_entries_inactive(void) ++{ ++ int i; ++ struct io_hdr_stats *shi = st_hdr_ionfs; ++ ++ for (i = 0; i < ionfs_nr; i++, shi++) { ++ shi->active = FALSE; ++ } ++} ++ ++/* ++ *************************************************************************** ++ * Free inactive entries (mark them as unused). ++ *************************************************************************** ++ */ ++void free_inactive_entries(void) ++{ ++ int i; ++ struct io_hdr_stats *shi = st_hdr_ionfs; ++ ++ for (i = 0; i < ionfs_nr; i++, shi++) { ++ if (!shi->active) { ++ shi->used = FALSE; ++ } ++ } ++} ++ ++/* ++ *************************************************************************** ++ * Allocate and init structures, according to system state. ++ *************************************************************************** ++ */ ++void io_sys_init(void) ++{ ++ int i; ++ ++ /* How many processors on this machine? */ ++ cpu_nr = get_cpu_nr(~0); ++ ++ /* Get number of NFS directories in /proc/self/mountstats */ ++ if ((ionfs_nr = get_nfs_mount_nr()) > 0) { ++ ionfs_nr += NR_NFS_PREALLOC; ++ } ++ if ((st_hdr_ionfs = (struct io_hdr_stats *) calloc(ionfs_nr, IO_HDR_STATS_SIZE)) == NULL) { ++ perror("malloc"); ++ exit(4); ++ } ++ ++ /* Allocate structures for number of NFS directories found */ ++ for (i = 0; i < 2; i++) { ++ if ((st_ionfs[i] = ++ (struct io_nfs_stats *) calloc(ionfs_nr, IO_NFS_STATS_SIZE)) == NULL) { ++ perror("malloc"); ++ exit(4); ++ } ++ } ++} ++ ++/* ++ *************************************************************************** ++ * Free various structures. ++ *************************************************************************** ++*/ ++void io_sys_free(void) ++{ ++ int i; ++ ++ /* Free I/O NFS directories structures */ ++ for (i = 0; i < 2; i++) { ++ ++ if (st_ionfs[i]) { ++ free(st_ionfs[i]); ++ } ++ } ++ ++ if (st_hdr_ionfs) { ++ free(st_hdr_ionfs); ++ } ++} ++ ++/* ++ *************************************************************************** ++ * Save stats for current NFS filesystem. ++ * ++ * IN: ++ * @name Name of NFS filesystem. ++ * @curr Index in array for current sample statistics. ++ * @st_io Structure with NFS statistics to save. ++ * @ionfs_nr Number of NFS filesystems. ++ * @st_hdr_ionfs Pointer on structures describing an NFS filesystem. ++ * ++ * OUT: ++ * @st_hdr_ionfs Pointer on structures describing an NFS filesystem. ++ *************************************************************************** ++ */ ++void save_stats(char *name, int curr, void *st_io) ++{ ++ int i, j; ++ struct io_hdr_stats *st_hdr_ionfs_i; ++ struct io_nfs_stats *st_ionfs_i; ++ ++ /* Look for NFS directory in data table */ ++ for (i = 0; i < ionfs_nr; i++) { ++ st_hdr_ionfs_i = st_hdr_ionfs + i; ++ if ((st_hdr_ionfs_i->used) && ++ (!strcmp(st_hdr_ionfs_i->name, name))) { ++ break; ++ } ++ } ++ ++ if (i == ionfs_nr) { ++ /* ++ * This is a new filesystem: Look for an unused entry to store it. ++ */ ++ for (i = 0; i < ionfs_nr; i++) { ++ st_hdr_ionfs_i = st_hdr_ionfs + i; ++ if (!st_hdr_ionfs_i->used) { ++ /* Unused entry found... */ ++ st_hdr_ionfs_i->used = TRUE; /* Indicate it is now used */ ++ st_hdr_ionfs_i->active = TRUE; ++ ++ strncpy(st_hdr_ionfs_i->name, name, MAX_NAME_LEN - 1); ++ st_hdr_ionfs_i->name[MAX_NAME_LEN - 1] = '\0'; ++ st_ionfs_i = st_ionfs[curr] + i; ++ memset(st_ionfs_i, 0, IO_NFS_STATS_SIZE); ++ *st_ionfs_i = *((struct io_nfs_stats *) st_io); ++ break; ++ } ++ } ++ if (i == ionfs_nr) { ++ /* All entries are used: The number has to be increased */ ++ ionfs_nr = ionfs_nr + 5; ++ ++ /* Increase the size of st_hdr_ionfs buffer */ ++ if ((st_hdr_ionfs = (struct io_hdr_stats *) ++ realloc(st_hdr_ionfs, ionfs_nr * IO_HDR_STATS_SIZE)) == NULL) { ++ perror("malloc"); ++ exit(4); ++ } ++ ++ /* Set the new entries inactive */ ++ for (j = 0; j < 5; j++) { ++ st_hdr_ionfs_i = st_hdr_ionfs + i + j; ++ st_hdr_ionfs_i->used = FALSE; ++ st_hdr_ionfs_i->active = FALSE; ++ } ++ ++ /* Increase the size of st_hdr_ionfs buffer */ ++ for (j = 0; j < 2; j++) { ++ if ((st_ionfs[j] = (struct io_nfs_stats *) ++ realloc(st_ionfs[j], ionfs_nr * IO_NFS_STATS_SIZE)) == NULL) { ++ perror("malloc"); ++ exit(4); ++ } ++ memset(st_ionfs[j] + i, 0, 5 * IO_NFS_STATS_SIZE); ++ } ++ ++ /* Now i shows the first unused entry of the new block */ ++ st_hdr_ionfs_i = st_hdr_ionfs + i; ++ st_hdr_ionfs_i->used = TRUE; /* Indicate it is now used */ ++ strncpy(st_hdr_ionfs_i->name, name, MAX_NAME_LEN - 1); ++ st_hdr_ionfs_i->name[MAX_NAME_LEN - 1] = '\0'; ++ st_ionfs_i = st_ionfs[curr] + i; ++ memset(st_ionfs_i, 0, IO_NFS_STATS_SIZE); ++ } ++ } else { ++ st_hdr_ionfs_i = st_hdr_ionfs + i; ++ st_hdr_ionfs_i->used = TRUE; ++ st_hdr_ionfs_i->active = TRUE; ++ st_ionfs_i = st_ionfs[curr] + i; ++ *st_ionfs_i = *((struct io_nfs_stats *) st_io); ++ } ++ /* ++ * else it was a new NFS directory ++ * but there was no free structure to store it. ++ */ ++} ++ ++/* ++ *************************************************************************** ++ * Read NFS-mount directories stats from /proc/self/mountstats. ++ * ++ * IN: ++ * @curr Index in array for current sample statistics. ++ *************************************************************************** ++ */ ++void read_nfs_stat(int curr) ++{ ++ FILE *fp; ++ int sw = 0; ++ char line[256]; ++ char *xprt_line; ++ char *mount_part; ++ char nfs_name[MAX_NAME_LEN]; ++ char mount[10], on[10], prefix[10], aux[32]; ++ char operation[16]; ++ struct io_nfs_stats snfs; ++ long int v1; ++ ++ /* Every I/O NFS entry is potentially unregistered */ ++ set_entries_inactive(); ++ ++ if ((fp = fopen(NFSMOUNTSTATS, "r")) == NULL) ++ return; ++ ++ sprintf(aux, "%%%ds", ++ MAX_NAME_LEN < 200 ? MAX_NAME_LEN-1 : 200); ++ ++ while (fgets(line, 256, fp) != NULL) { ++ /* Read NFS directory name */ ++ if (!strncmp(line, "device", 6)) { ++ sw = 0; ++ sscanf(line + 6, aux, nfs_name); ++ mount_part = strchr(line + 7, ' '); ++ if (mount_part != NULL) { ++ sscanf(mount_part, "%9s %9s", mount, on); ++ if ((!strncmp(mount, "mounted", 7)) && (!strncmp(on, "on", 2))) { ++ sw = 1; ++ } ++ } ++ } ++ ++ sscanf(line, "%9s", prefix); ++ if (sw && (!strncmp(prefix, "bytes:", 6))) { ++ /* Read the stats for the last NFS-mounted directory */ ++ sscanf(strstr(line, "bytes:") + 6, "%llu %llu %llu %llu %llu %llu", ++ &snfs.rd_normal_bytes, &snfs.wr_normal_bytes, ++ &snfs.rd_direct_bytes, &snfs.wr_direct_bytes, ++ &snfs.rd_server_bytes, &snfs.wr_server_bytes); ++ sw = 2; ++ } ++ ++ if ((sw == 2) && (!strncmp(prefix, "xprt:", 5))) { ++ /* ++ * Read extended statistic for the last NFS-mounted directory ++ * - number of sent rpc requests. ++ */ ++ xprt_line = (strstr(line, "xprt:") + 6); ++ /* udp, tcp or rdma data */ ++ if (!strncmp(xprt_line, "udp", 3)) { ++ /* port bind_count sends recvs (bad_xids req_u bklog_u) */ ++ sscanf(strstr(xprt_line, "udp") + 4, "%*u %*u %lu", ++ &snfs.rpc_sends); ++ } ++ if (!strncmp(xprt_line, "tcp", 3)) { ++ /* ++ * port bind_counter connect_count connect_time idle_time ++ * sends recvs (bad_xids req_u bklog_u) ++ */ ++ sscanf(strstr(xprt_line, "tcp") + 4, ++ "%*u %*u %*u %*u %*d %lu", ++ &snfs.rpc_sends); ++ } ++ if (!strncmp(xprt_line,"rdma", 4)) { ++ /* ++ * 0(port) bind_count connect_count connect_time idle_time ++ * sends recvs (bad_xids req_u bklog_u...) ++ */ ++ sscanf(strstr(xprt_line, "rdma") + 5, ++ "%*u %*u %*u %*u %*d %lu", ++ &snfs.rpc_sends); ++ } ++ sw = 3; ++ } ++ ++ if ((sw == 3) && (!strncmp(prefix, "per-op", 6))) { ++ sw = 4; ++ while (sw == 4) { ++ if (fgets(line, sizeof(line), fp) == NULL) ++ break; ++ sscanf(line, "%15s %lu", operation, &v1); ++ if (!strncmp(operation, "READ:", 5)) { ++ snfs.nfs_rops = v1; ++ } ++ else if (!strncmp(operation, "WRITE:", 6)) { ++ snfs.nfs_wops = v1; ++ ++ save_stats(nfs_name, curr, &snfs); ++ sw = 0; ++ } ++ } ++ } ++ } ++ ++ fclose(fp); ++ ++ /* Free structures corresponding to unregistered filesystems */ ++ free_inactive_entries(); ++} ++ ++/* ++ *************************************************************************** ++ * Display NFS stats header. ++ * ++ * OUT: ++ * @fctr Conversion factor. ++ *************************************************************************** ++ */ ++void write_nfs_stat_header(int *fctr) ++{ ++ printf("Filesystem: "); ++ if (DISPLAY_KILOBYTES(flags)) { ++ printf(" rkB_nor/s wkB_nor/s rkB_dir/s wkB_dir/s" ++ " rkB_svr/s wkB_svr/s"); ++ *fctr = 1024; ++ } ++ else if (DISPLAY_MEGABYTES(flags)) { ++ printf(" rMB_nor/s wMB_nor/s rMB_dir/s wMB_dir/s" ++ " rMB_svr/s wMB_svr/s"); ++ *fctr = 1024 * 1024; ++ } ++ else { ++ printf(" rBlk_nor/s wBlk_nor/s rBlk_dir/s wBlk_dir/s" ++ " rBlk_svr/s wBlk_svr/s"); ++ *fctr = 512; ++ } ++ printf(" ops/s rops/s wops/s\n"); ++} ++ ++/* ++ *************************************************************************** ++ * Write NFS stats read from /proc/self/mountstats. ++ * ++ * IN: ++ * @curr Index in array for current sample statistics. ++ * @itv Interval of time. ++ * @fctr Conversion factor. ++ * @shi Structures describing the NFS filesystems. ++ * @ioi Current sample statistics. ++ * @ioj Previous sample statistics. ++ *************************************************************************** ++ */ ++void write_nfs_stat(int curr, unsigned long long itv, int fctr, ++ struct io_hdr_stats *shi, struct io_nfs_stats *ioni, ++ struct io_nfs_stats *ionj) ++{ ++ if (DISPLAY_HUMAN_READ(flags)) { ++ printf("%-22s\n%23s", shi->name, ""); ++ } ++ else { ++ printf("%-22s ", shi->name); ++ } ++ printf("%12.2f %12.2f %12.2f %12.2f %12.2f %12.2f %9.2f %9.2f %9.2f\n", ++ S_VALUE(ionj->rd_normal_bytes, ioni->rd_normal_bytes, itv) / fctr, ++ S_VALUE(ionj->wr_normal_bytes, ioni->wr_normal_bytes, itv) / fctr, ++ S_VALUE(ionj->rd_direct_bytes, ioni->rd_direct_bytes, itv) / fctr, ++ S_VALUE(ionj->wr_direct_bytes, ioni->wr_direct_bytes, itv) / fctr, ++ S_VALUE(ionj->rd_server_bytes, ioni->rd_server_bytes, itv) / fctr, ++ S_VALUE(ionj->wr_server_bytes, ioni->wr_server_bytes, itv) / fctr, ++ S_VALUE(ionj->rpc_sends, ioni->rpc_sends, itv), ++ S_VALUE(ionj->nfs_rops, ioni->nfs_rops, itv), ++ S_VALUE(ionj->nfs_wops, ioni->nfs_wops, itv)); ++} ++ ++/* ++ *************************************************************************** ++ * Print everything now (stats and uptime). ++ * ++ * IN: ++ * @curr Index in array for current sample statistics. ++ * @rectime Current date and time. ++ *************************************************************************** ++ */ ++void write_stats(int curr, struct tm *rectime) ++{ ++ int i, fctr = 1; ++ unsigned long long itv; ++ struct io_hdr_stats *shi; ++ struct io_nfs_stats *ioni, *ionj; ++ ++ /* Test stdout */ ++ TEST_STDOUT(STDOUT_FILENO); ++ ++ /* Print time stamp */ ++ if (DISPLAY_TIMESTAMP(flags)) { ++ if (DISPLAY_ISO(flags)) { ++ strftime(timestamp, sizeof(timestamp), "%FT%T%z", rectime); ++ } ++ else { ++ strftime(timestamp, sizeof(timestamp), "%x %X", rectime); ++ } ++ printf("%s\n", timestamp); ++#ifdef DEBUG ++ if (DISPLAY_DEBUG(flags)) { ++ fprintf(stderr, "%s\n", timestamp); ++ } ++#endif ++ } ++ ++ /* Interval of time, reduced to one processor */ ++ itv = get_interval(uptime0[!curr], uptime0[curr]); ++ ++ shi = st_hdr_ionfs; ++ ++ /* Display NFS stats header */ ++ write_nfs_stat_header(&fctr); ++ ++ for (i = 0; i < ionfs_nr; i++, shi++) { ++ if (shi->used) { ++ ioni = st_ionfs[curr] + i; ++ ionj = st_ionfs[!curr] + i; ++#ifdef DEBUG ++ if (DISPLAY_DEBUG(flags)) { ++ /* Debug output */ ++ fprintf(stderr, "name=%s itv=%llu fctr=%d ioni{ rd_normal_bytes=%llu " ++ "wr_normal_bytes=%llu rd_direct_bytes=%llu wr_direct_bytes=%llu rd_server_bytes=%llu " ++ "wr_server_bytes=%llu rpc_sends=%lu nfs_rops=%lu nfs_wops=%lu }\n", ++ shi->name, itv, fctr, ++ ioni->rd_normal_bytes, ioni->wr_normal_bytes, ++ ioni->rd_direct_bytes, ioni->wr_direct_bytes, ++ ioni->rd_server_bytes, ioni->wr_server_bytes, ++ ioni->rpc_sends, ++ ioni->nfs_rops, ioni->nfs_wops); ++ } ++#endif ++ write_nfs_stat(curr, itv, fctr, shi, ioni, ionj); ++ } ++ } ++ printf("\n"); ++} ++ ++/* ++ *************************************************************************** ++ * Main loop: Read stats from the relevant sources and display them. ++ * ++ * IN: ++ * @count Number of lines of stats to print. ++ * @rectime Current date and time. ++ *************************************************************************** ++ */ ++void rw_io_stat_loop(long int count, struct tm *rectime) ++{ ++ int curr = 1; ++ ++ /* Don't buffer data if redirected to a pipe */ ++ setbuf(stdout, NULL); ++ ++ do { ++ /* Read system uptime (reduced to one processor) */ ++ uptime0[curr] = 0; ++ read_uptime(&(uptime0[curr])); ++ if (!uptime0[curr]) ++ /* Cannot read system uptime (/proc/uptime doesn't exist) */ ++ exit(2); ++ ++ /* Read NFS directories stats */ ++ read_nfs_stat(curr); ++ ++ /* Get time */ ++ get_localtime(rectime, 0); ++ ++ /* Print results */ ++ write_stats(curr, rectime); ++ ++ if (count > 0) { ++ count--; ++ } ++ if (count) { ++ curr ^= 1; ++ pause(); ++ } ++ } ++ while (count); ++} ++ ++/* ++ *************************************************************************** ++ * Main entry to the nfsiostat-sysstat program. ++ *************************************************************************** ++ */ ++int main(int argc, char **argv) ++{ ++ int it = 0; ++ int opt = 1; ++ int i; ++ long count = 1; ++ struct utsname header; ++ struct tm rectime; ++ ++#ifdef USE_NLS ++ /* Init National Language Support */ ++ init_nls(); ++#endif ++ ++ /* Get HZ */ ++ get_HZ(); ++ ++ /* Process args... */ ++ while (opt < argc) { ++ ++#ifdef DEBUG ++ if (!strcmp(argv[opt], "--debuginfo")) { ++ flags |= I_D_DEBUG; ++ opt++; ++ } else ++#endif ++ if (!strncmp(argv[opt], "-", 1)) { ++ for (i = 1; *(argv[opt] + i); i++) { ++ ++ switch (*(argv[opt] + i)) { ++ ++ case 'h': ++ /* Display an easy-to-read NFS report */ ++ flags |= I_D_HUMAN_READ; ++ break; ++ ++ case 'k': ++ if (DISPLAY_MEGABYTES(flags)) { ++ usage(argv[0]); ++ } ++ /* Display stats in kB/s */ ++ flags |= I_D_KILOBYTES; ++ break; ++ ++ case 'm': ++ if (DISPLAY_KILOBYTES(flags)) { ++ usage(argv[0]); ++ } ++ /* Display stats in MB/s */ ++ flags |= I_D_MEGABYTES; ++ break; ++ ++ case 't': ++ /* Display timestamp */ ++ flags |= I_D_TIMESTAMP; ++ break; ++ ++ case 'V': ++ /* Print version number and exit */ ++ print_version(); ++ break; ++ ++ default: ++ usage(argv[0]); ++ } ++ } ++ opt++; ++ } ++ ++ else if (!it) { ++ interval = atol(argv[opt++]); ++ if (interval < 0) { ++ usage(argv[0]); ++ } ++ count = -1; ++ it = 1; ++ } ++ ++ else if (it > 0) { ++ count = atol(argv[opt++]); ++ if ((count < 1) || !interval) { ++ usage(argv[0]); ++ } ++ it = -1; ++ } ++ else { ++ usage(argv[0]); ++ } ++ } ++ ++ if (!interval) { ++ count = 1; ++ } ++ ++ /* Select output unit (kB/s or blocks/s) */ ++ set_output_unit(); ++ ++ /* Init structures according to machine architecture */ ++ io_sys_init(); ++ ++ get_localtime(&rectime, 0); ++ ++ /* Get system name, release number and hostname */ ++ uname(&header); ++ if (print_gal_header(&rectime, header.sysname, header.release, ++ header.nodename, header.machine, cpu_nr)) { ++ flags |= I_D_ISO; ++ } ++ printf("\n"); ++ ++ /* Set a handler for SIGALRM */ ++ memset(&alrm_act, 0, sizeof(alrm_act)); ++ alrm_act.sa_handler = (void *) alarm_handler; ++ sigaction(SIGALRM, &alrm_act, NULL); ++ alarm(interval); ++ ++ /* Main loop */ ++ rw_io_stat_loop(count, &rectime); ++ ++ /* Free structures */ ++ io_sys_free(); ++ ++ return 0; ++} +diff -uprN sysstat-10.1.5.orig/nfsiostat-sysstat.h sysstat-10.1.5/nfsiostat-sysstat.h +--- sysstat-10.1.5.orig/nfsiostat-sysstat.h 1970-01-01 01:00:00.000000000 +0100 ++++ sysstat-10.1.5/nfsiostat-sysstat.h 2016-05-24 18:25:16.210668308 +0200 +@@ -0,0 +1,57 @@ ++/* ++ * nfsiostat-sysstat: Report NFS I/O statistics ++ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved ++ * Written by Ivana Varekova ++ */ ++ ++#ifndef _NFSIOSTAT_SYSSTAT_H ++#define _NFSIOSTAT_SYSSTAT_H ++ ++#include "common.h" ++ ++#define NFSMOUNTSTATS "/proc/self/mountstats" ++ ++/* I_: iostat - D_: Display - F_: Flag */ ++#define I_D_TIMESTAMP 0x001 ++#define I_D_KILOBYTES 0x002 ++#define I_D_MEGABYTES 0x004 ++#define I_D_ISO 0x008 ++#define I_D_HUMAN_READ 0x010 ++#define I_D_DEBUG 0x020 ++ ++#define DISPLAY_TIMESTAMP(m) (((m) & I_D_TIMESTAMP) == I_D_TIMESTAMP) ++#define DISPLAY_KILOBYTES(m) (((m) & I_D_KILOBYTES) == I_D_KILOBYTES) ++#define DISPLAY_MEGABYTES(m) (((m) & I_D_MEGABYTES) == I_D_MEGABYTES) ++#define DISPLAY_ISO(m) (((m) & I_D_ISO) == I_D_ISO) ++#define DISPLAY_HUMAN_READ(m) (((m) & I_D_HUMAN_READ) == I_D_HUMAN_READ) ++#define DISPLAY_DEBUG(m) (((m) & I_D_DEBUG) == I_D_DEBUG) ++ ++/* Environment variable */ ++#define ENV_POSIXLY_CORRECT "POSIXLY_CORRECT" ++ ++/* Preallocation constats */ ++#define NR_NFS_PREALLOC 2 ++ ++struct io_nfs_stats { ++ unsigned long long rd_normal_bytes __attribute__ ((aligned (8))); ++ unsigned long long wr_normal_bytes __attribute__ ((packed)); ++ unsigned long long rd_direct_bytes __attribute__ ((packed)); ++ unsigned long long wr_direct_bytes __attribute__ ((packed)); ++ unsigned long long rd_server_bytes __attribute__ ((packed)); ++ unsigned long long wr_server_bytes __attribute__ ((packed)); ++ unsigned long rpc_sends __attribute__ ((packed)); ++ unsigned long nfs_rops __attribute__ ((packed)); ++ unsigned long nfs_wops __attribute__ ((packed)); ++}; ++ ++#define IO_NFS_STATS_SIZE (sizeof(struct io_nfs_stats)) ++ ++struct io_hdr_stats { ++ unsigned int active __attribute__ ((aligned (4))); ++ unsigned int used __attribute__ ((packed)); ++ char name[MAX_NAME_LEN]; ++}; ++ ++#define IO_HDR_STATS_SIZE (sizeof(struct io_hdr_stats)) ++ ++#endif /* _NFSIOSTAT_SYSSTAT_H */ diff --git a/SOURCES/sysstat-10.1.5-overwrite-sa.patch b/SOURCES/sysstat-10.1.5-overwrite-sa.patch new file mode 100644 index 0000000..1b72d7b --- /dev/null +++ b/SOURCES/sysstat-10.1.5-overwrite-sa.patch @@ -0,0 +1,37 @@ +diff -ur sysstat-10.1.5.orig/sa1.in sysstat-10.1.5/sa1.in +--- sysstat-10.1.5.orig/sa1.in 2012-05-13 15:00:56.000000000 +0200 ++++ sysstat-10.1.5/sa1.in 2014-09-01 21:56:13.197869126 +0200 +@@ -10,15 +10,15 @@ + # Used only if ${SYSCONFIG_DIR}/sysstat doesn't exist! + HISTORY=0 + SADC_OPTIONS="" +- ++DDIR=@SA_DIR@ ++DATE=`date +%d` ++CURRENTFILE=sa${DATE} ++CURRENTDIR=`date +%Y%m` + SYSCONFIG_DIR=@SYSCONFIG_DIR@ ++umask 0022 + [ -r ${SYSCONFIG_DIR}/sysstat ] && . ${SYSCONFIG_DIR}/sysstat + if [ ${HISTORY} -gt 28 ] + then +- CURRENTDIR=`date +%Y%m` +- DATE=`date +%d` +- CURRENTFILE=sa${DATE} +- DDIR=@SA_DIR@ + cd ${DDIR} || exit 1 + [ -d ${CURRENTDIR} ] || mkdir -p ${CURRENTDIR} + # If ${CURRENTFILE} exists and is a regular file, then make sure +@@ -33,8 +33,11 @@ + # the (new) current file + rm -f ${CURRENTFILE} + ln -s ${CURRENTDIR}/${CURRENTFILE} ${CURRENTFILE} ++else ++ # If ${CURRENTFILE} exists, is a regular file and is from a previous ++ # month then delete it so that it is recreated by sadc afresh ++ [ -f ${CURRENTFILE} ] && [ "`date +%Y%m -r ${CURRENTFILE}`" -lt "${CURRENTDIR}" ] && rm -f ${CURRENTFILE} + fi +-umask 0022 + ENDIR=@SA_LIB_DIR@ + cd ${ENDIR} + [ "$1" = "--boot" ] && shift && BOOT=y || BOOT=n diff --git a/SOURCES/sysstat-10.1.5-pids-prealloc.patch b/SOURCES/sysstat-10.1.5-pids-prealloc.patch new file mode 100644 index 0000000..23d9a59 --- /dev/null +++ b/SOURCES/sysstat-10.1.5-pids-prealloc.patch @@ -0,0 +1,209 @@ +diff -upr sysstat-10.1.5.orig/common.h sysstat-10.1.5/common.h +--- sysstat-10.1.5.orig/common.h 2013-03-23 17:31:46.000000000 +0100 ++++ sysstat-10.1.5/common.h 2016-04-29 12:47:09.285214132 +0200 +@@ -106,9 +106,12 @@ + * + * NB: Define SP_VALUE() to normalize to %; + * HZ is 1024 on IA64 and % should be normalized to 100. ++ * SP_VALUE_100() will not output value bigger than 100; this is needed for some ++ * corner cases, should be used with care. + */ + #define S_VALUE(m,n,p) (((double) ((n) - (m))) / (p) * HZ) + #define SP_VALUE(m,n,p) (((double) ((n) - (m))) / (p) * 100) ++#define SP_VALUE_100(m,n,p) MINIMUM((((double) ((n) - (m))) / (p) * 100),100) + + /* + * Under very special circumstances, STDOUT may become unavailable. +diff -upr sysstat-10.1.5.orig/pidstat.c sysstat-10.1.5/pidstat.c +--- sysstat-10.1.5.orig/pidstat.c 2013-03-23 17:31:46.000000000 +0100 ++++ sysstat-10.1.5/pidstat.c 2016-04-29 13:04:02.672402150 +0200 +@@ -152,15 +152,35 @@ void salloc_pid_array(unsigned int len) + */ + void salloc_pid(unsigned int len) + { +- int i; ++ short i; ++ ++ for (i = 0; i < 3; i++) { ++ if ((st_pid_list[i] = (struct pid_stats *) calloc(len, PID_STATS_SIZE)) == NULL) { ++ perror("calloc"); ++ exit(4); ++ } ++ } ++} ++ ++/* ++ *************************************************************************** ++ * Reallocate structures for PIDs to read. ++ *************************************************************************** ++ */ ++void realloc_pid(void) ++{ ++ short i; ++ unsigned int new_size = 2 * pid_nr; + + for (i = 0; i < 3; i++) { +- if ((st_pid_list[i] = (struct pid_stats *) malloc(PID_STATS_SIZE * len)) == NULL) { +- perror("malloc"); ++ if ((st_pid_list[i] = (struct pid_stats *) realloc(st_pid_list[i], PID_STATS_SIZE * new_size)) == NULL) { ++ perror("realloc"); + exit(4); + } +- memset(st_pid_list[i], 0, PID_STATS_SIZE * len); ++ memset(st_pid_list[i] + pid_nr, 0, PID_STATS_SIZE * (new_size - pid_nr)); + } ++ ++ pid_nr = new_size; + } + + /* +@@ -774,23 +794,22 @@ void read_task_stats(int curr, unsigned + if ((dir = opendir(filename)) == NULL) + return; + +- while (*index < pid_nr) { ++ while ((drp = readdir(dir)) != NULL) { ++ if (!isdigit(drp->d_name[0])) { ++ continue; ++ } + +- while ((drp = readdir(dir)) != NULL) { +- if (isdigit(drp->d_name[0])) +- break; ++ pst = st_pid_list[curr] + (*index)++; ++ if (read_pid_stats(atoi(drp->d_name), pst, &thr_nr, pid)) { ++ /* Thread no longer exists */ ++ pst->pid = 0; + } + +- if (drp) { +- pst = st_pid_list[curr] + (*index)++; +- if (read_pid_stats(atoi(drp->d_name), pst, &thr_nr, pid)) { +- /* Thread no longer exists */ +- pst->pid = 0; +- } ++ if (*index >= pid_nr) { ++ realloc_pid(); + } +- else +- break; + } ++ + closedir(dir); + } + +@@ -830,36 +849,34 @@ void read_stats(int curr) + exit(4); + } + +- while (p < pid_nr) { ++ /* Get directory entries */ ++ while ((drp = readdir(dir)) != NULL) { ++ if (!isdigit(drp->d_name[0])) { ++ continue; ++ } ++ ++ pst = st_pid_list[curr] + p++; ++ pid = atoi(drp->d_name); ++ ++ if (read_pid_stats(pid, pst, &thr_nr, 0)) { ++ /* Process has terminated */ ++ pst->pid = 0; ++ } else if (DISPLAY_TID(pidflag)) { ++ /* Read stats for threads in task subdirectory */ ++ read_task_stats(curr, pid, &p); + +- /* Get directory entries */ +- while ((drp = readdir(dir)) != NULL) { +- if (isdigit(drp->d_name[0])) +- break; +- } +- if (drp) { +- pst = st_pid_list[curr] + p++; +- pid = atoi(drp->d_name); +- +- if (read_pid_stats(pid, pst, &thr_nr, 0)) { +- /* Process has terminated */ +- pst->pid = 0; +- } +- +- else if (DISPLAY_TID(pidflag)) { +- /* Read stats for threads in task subdirectory */ +- read_task_stats(curr, pid, &p); +- } +- } +- else { +- for (q = p; q < pid_nr; q++) { +- pst = st_pid_list[curr] + q; +- pst->pid = 0; +- } +- break; + } ++ ++ if (p >= pid_nr) { ++ realloc_pid(); ++ } + } + ++ for (q = p; q < pid_nr; q++) { ++ pst = st_pid_list[curr] + q; ++ pst->pid = 0; ++ } ++ + /* Close /proc directory */ + closedir(dir); + } +@@ -1174,15 +1191,15 @@ int write_pid_task_all_stats(int prev, i + printf(" %7.2f %7.2f %7.2f %7.2f", + (pstc->utime - pstc->gtime) < (pstp->utime - pstp->gtime) ? + 0.0 : +- SP_VALUE(pstp->utime - pstp->gtime, ++ SP_VALUE_100(pstp->utime - pstp->gtime, + pstc->utime - pstc->gtime, itv), +- SP_VALUE(pstp->stime, pstc->stime, itv), +- SP_VALUE(pstp->gtime, pstc->gtime, itv), ++ SP_VALUE_100(pstp->stime, pstc->stime, itv), ++ SP_VALUE_100(pstp->gtime, pstc->gtime, itv), + /* User time already includes guest time */ + IRIX_MODE_OFF(pidflag) ? +- SP_VALUE(pstp->utime + pstp->stime, ++ SP_VALUE_100(pstp->utime + pstp->stime, + pstc->utime + pstc->stime, g_itv) : +- SP_VALUE(pstp->utime + pstp->stime, ++ SP_VALUE_100(pstp->utime + pstp->stime, + pstc->utime + pstc->stime, itv)); + + printf(" %3d", pstc->processor); +@@ -1351,15 +1368,15 @@ int write_pid_task_cpu_stats(int prev, i + printf(" %7.2f %7.2f %7.2f %7.2f", + (pstc->utime - pstc->gtime) < (pstp->utime - pstp->gtime) ? + 0.0 : +- SP_VALUE(pstp->utime - pstp->gtime, ++ SP_VALUE_100(pstp->utime - pstp->gtime, + pstc->utime - pstc->gtime, itv), +- SP_VALUE(pstp->stime, pstc->stime, itv), +- SP_VALUE(pstp->gtime, pstc->gtime, itv), ++ SP_VALUE_100(pstp->stime, pstc->stime, itv), ++ SP_VALUE_100(pstp->gtime, pstc->gtime, itv), + /* User time already includes guest time */ + IRIX_MODE_OFF(pidflag) ? +- SP_VALUE(pstp->utime + pstp->stime, ++ SP_VALUE_100(pstp->utime + pstp->stime, + pstc->utime + pstc->stime, g_itv) : +- SP_VALUE(pstp->utime + pstp->stime, ++ SP_VALUE_100(pstp->utime + pstp->stime, + pstc->utime + pstc->stime, itv)); + + if (!disp_avg) { +diff -upr sysstat-10.1.5.orig/pidstat.h sysstat-10.1.5/pidstat.h +--- sysstat-10.1.5.orig/pidstat.h 2013-03-23 17:31:46.000000000 +0100 ++++ sysstat-10.1.5/pidstat.h 2016-04-28 18:24:37.700124018 +0200 +@@ -13,7 +13,7 @@ + #define K_P_CHILD "CHILD" + #define K_P_ALL "ALL" + +-#define NR_PID_PREALLOC 10 ++#define NR_PID_PREALLOC 100 + + #define MAX_COMM_LEN 128 + #define MAX_CMDLINE_LEN 128 diff --git a/SOURCES/sysstat-10.1.5-sa2-xz.patch b/SOURCES/sysstat-10.1.5-sa2-xz.patch new file mode 100644 index 0000000..ea352d3 --- /dev/null +++ b/SOURCES/sysstat-10.1.5-sa2-xz.patch @@ -0,0 +1,12 @@ +diff -ur sysstat-10.1.5.orig/sa2.in sysstat-10.1.5/sa2.in +--- sysstat-10.1.5.orig/sa2.in 2012-03-15 16:48:56.000000000 +0100 ++++ sysstat-10.1.5/sa2.in 2014-09-01 22:10:39.901270008 +0200 +@@ -50,7 +50,7 @@ + cd ${ENDIR} + [ -L ${RPT} ] && rm -f ${RPT} + ${ENDIR}/sar $* -f ${DFILE} > ${RPT} +-find ${DDIR} \( -name 'sar??' -o -name 'sa??' -o -name 'sar??.gz' -o -name 'sa??.gz' -o -name 'sar??.bz2' -o -name 'sa??.bz2' \) \ ++find ${DDIR} \( -name 'sar??' -o -name 'sa??' -o -name 'sar??.xz' -o -name 'sa??.xz' -o -name 'sar??.gz' -o -name 'sa??.gz' -o -name 'sar??.bz2' -o -name 'sa??.bz2' \) \ + -mtime +"${HISTORY}" -exec rm -f {} \; + find ${DDIR} \( -name 'sar??' -o -name 'sa??' \) -type f -mtime +"${COMPRESSAFTER}" \ + -exec ${ZIP} {} \; > /dev/null 2>&1 diff --git a/SOURCES/sysstat-10.1.5-single-cpu-cifs.patch b/SOURCES/sysstat-10.1.5-single-cpu-cifs.patch new file mode 100644 index 0000000..a6c72a7 --- /dev/null +++ b/SOURCES/sysstat-10.1.5-single-cpu-cifs.patch @@ -0,0 +1,99 @@ +diff -upr sysstat-10.1.5.orig/cifsiostat.c sysstat-10.1.5/cifsiostat.c +--- sysstat-10.1.5.orig/cifsiostat.c 2013-03-23 17:31:46.000000000 +0100 ++++ sysstat-10.1.5/cifsiostat.c 2014-09-29 14:23:37.600574444 +0200 +@@ -43,7 +43,6 @@ + #define SCCSID "@(#)sysstat-" VERSION ": " __FILE__ " compiled " __DATE__ " " __TIME__ + char *sccsid(void) { return (SCCSID); } + +-unsigned long long uptime[2] = {0, 0}; + unsigned long long uptime0[2] = {0, 0}; + struct cifs_stats *st_cifs[2]; + struct io_hdr_stats *st_hdr_cifs; +@@ -474,13 +473,8 @@ void write_stats(int curr, struct tm *re + #endif + } + +- /* Interval is multiplied by the number of processors */ +- itv = get_interval(uptime[!curr], uptime[curr]); +- +- if (cpu_nr > 1) { +- /* On SMP machines, reduce itv to one processor (see note above) */ +- itv = get_interval(uptime0[!curr], uptime0[curr]); +- } ++ /* Interval of time, reduced to one processor */ ++ itv = get_interval(uptime0[!curr], uptime0[curr]); + + shi = st_hdr_cifs; + +@@ -527,15 +521,12 @@ void rw_io_stat_loop(long int count, str + setbuf(stdout, NULL); + + do { +- if (cpu_nr > 1) { +- /* +- * Read system uptime (only for SMP machines). +- * Init uptime0. So if /proc/uptime cannot fill it, +- * this will be done by /proc/stat. +- */ +- uptime0[curr] = 0; +- read_uptime(&(uptime0[curr])); +- } ++ /* Read system uptime (reduced to one processor) */ ++ uptime0[curr] = 0; ++ read_uptime(&(uptime0[curr])); ++ if (!uptime0[curr]) ++ /* Cannot read system uptime (/proc/uptime doesn't exist) */ ++ exit(2); + + /* Read CIFS stats */ + read_cifs_stat(curr); +diff -upr sysstat-10.1.5.orig/nfsiostat.c sysstat-10.1.5/nfsiostat.c +--- sysstat-10.1.5.orig/nfsiostat.c 2013-03-23 17:31:46.000000000 +0100 ++++ sysstat-10.1.5/nfsiostat.c 2014-09-29 14:23:37.601574440 +0200 +@@ -42,7 +42,6 @@ + #define SCCSID "@(#)sysstat-" VERSION ": " __FILE__ " compiled " __DATE__ " " __TIME__ + char *sccsid(void) { return (SCCSID); } + +-unsigned long long uptime[2] = {0, 0}; + unsigned long long uptime0[2] = {0, 0}; + struct io_nfs_stats *st_ionfs[2]; + struct io_hdr_stats *st_hdr_ionfs; +@@ -541,13 +540,8 @@ void write_stats(int curr, struct tm *re + #endif + } + +- /* Interval is multiplied by the number of processors */ +- itv = get_interval(uptime[!curr], uptime[curr]); +- +- if (cpu_nr > 1) { +- /* On SMP machines, reduce itv to one processor (see note above) */ +- itv = get_interval(uptime0[!curr], uptime0[curr]); +- } ++ /* Interval of time, reduced to one processor */ ++ itv = get_interval(uptime0[!curr], uptime0[curr]); + + shi = st_hdr_ionfs; + +@@ -595,15 +589,13 @@ void rw_io_stat_loop(long int count, str + setbuf(stdout, NULL); + + do { +- if (cpu_nr > 1) { +- /* +- * Read system uptime (only for SMP machines). +- * Init uptime0. So if /proc/uptime cannot fill it, +- * this will be done by /proc/stat. +- */ +- uptime0[curr] = 0; +- read_uptime(&(uptime0[curr])); +- } ++ /* Read system uptime (reduced to one processor) */ ++ uptime0[curr] = 0; ++ read_uptime(&(uptime0[curr])); ++ if (!uptime0[curr]) ++ /* Cannot read system uptime (/proc/uptime doesn't exist) */ ++ exit(2); ++ + /* Read NFS directories stats */ + read_nfs_stat(curr); + diff --git a/SOURCES/sysstat-10.1.5-sysstat-5.patch b/SOURCES/sysstat-10.1.5-sysstat-5.patch new file mode 100644 index 0000000..0818849 --- /dev/null +++ b/SOURCES/sysstat-10.1.5-sysstat-5.patch @@ -0,0 +1,118 @@ +diff -ur sysstat-10.1.5.orig/man/sysstat.in sysstat-10.1.5/man/sysstat.in +--- sysstat-10.1.5.orig/man/sysstat.in 2010-09-22 22:07:29.000000000 +0200 ++++ sysstat-10.1.5/man/sysstat.in 2014-09-01 22:50:58.614499671 +0200 +@@ -11,17 +11,99 @@ + configure sysstat logging. + The variables and their meanings are: + .TP ++.B COMPRESSAFTER ++Number of days after which daily data files are to be compressed. ++The compression program is given in the ++.B ZIP ++variable. ++ ++.TP + .B HISTORY + The number of days during which a daily data file or a report + should be kept. Data files or reports older than this number of + days will be removed by the + .BR sa2 (8) + shell script. ++Data files and reports are normally saved in the @SA_DIR@ directory, ++under the name ++.IR saDD ++(for data files) or ++.IR sarDD ++(for reports), where the DD parameter indicates the current day. + +-.TP +-.B COMPRESSAFTER +-Number of days after which daily data files are to be compressed, +-either by gzip or bzip2. ++The number of files actually kept in the @SA_DIR@ directory may be ++slightly higher than the ++.B HISTORY ++value due to the way the ++.B sa2 ++script figures ++out which files are to be removed (see below "How the ++.BR sa2 (8) ++script applies ++.B HISTORY ++value"). Using a value of 28 keeps a whole month's worth of data. ++ ++How the ++.BR sa2 (8) ++script applies ++.B HISTORY ++value ++ ++The ++.B sa2 ++script uses the "find" command with the "-mtime" option to figure ++out which files are to be removed. The "find" command interprets this value ++as "N 24 hour periods", ignoring any fractional part. This means that the ++last modified time of a given sa[r]DD data or report file, using a ++.B HISTORY ++of 1, has to have been modified at least two days ago before it will be ++removed. And for a ++.B HISTORY ++of 28 that would mean 29 days ago. ++ ++To figure out how a ++.B HISTORY ++of 28 is applied in practice, we need to ++consider that the ++.B sa2 ++script that issues the "find" command to remove the ++old files typically runs just before mid-night on a given system, and since ++the first record from ++.B sadc ++can also be written to the previous day's data file ++(thereby moving its modification time up a bit), the ++.B sa2 ++script will leave ++30 files untouched. So for a setting of 28, and counting the data file of ++the current day, there will always be 31 files (or 30 files, depending on the ++number of days in a month) in the @SA_DIR@ directory during the majority ++of a given day. E.g.: ++ ++April 30th: 31 files (Apr 30th-1st, Mar 31th) ++.br ++May 1st: 30 files (May 1st, Apr 30th-2nd) ++ ++Yet we can note the following exceptions (as inspected at Noon of the given ++day): ++ ++February 28th: 31 files (Feb 28th-1st, Jan 31st, 30th & 29th) ++.br ++March 1st: 30 files (Mar 1st, Feb 28th-2nd, Jan 31st & 30th) ++.br ++March 2nd: 29 files (Mar 1st & 2nd, Feb 28th-3rd, Jan. 31st) ++.br ++March 3rd: 28 files (Mar 1st-3rd, Feb 28th-4th) ++.br ++March 4th - March 28th: 28 files ++.br ++March 29th: 29 files ++.br ++March 30th: 30 files ++.br ++March 31st: 31 files ++ ++(Determining the number of files in March on a leap year is left as an ++exercise for the reader). + + .TP + .B SADC_OPTIONS +@@ -34,6 +116,10 @@ + These options are used only when a new data file is created. They will be + ignored with an already existing one. + ++.TP ++.B ZIP ++Program used to compress data and report files. ++ + .SH FILES + .IR @SYSCONFIG_DIR@/sysstat + diff --git a/SOURCES/sysstat-10.1.5-tapestat.patch b/SOURCES/sysstat-10.1.5-tapestat.patch new file mode 100644 index 0000000..50ab274 --- /dev/null +++ b/SOURCES/sysstat-10.1.5-tapestat.patch @@ -0,0 +1,1124 @@ +diff -uprN sysstat-10.1.5.orig/Makefile.in sysstat-10.1.5/Makefile.in +--- sysstat-10.1.5.orig/Makefile.in 2016-06-01 12:46:28.193462305 +0200 ++++ sysstat-10.1.5/Makefile.in 2016-06-01 12:46:52.027338556 +0200 +@@ -160,7 +160,7 @@ NLSPOT= $(NLSPO:.po=.pot) + % : %.o + $(CC) -o $@ $(CFLAGS) $^ $(LFLAGS) + +-all: sadc sar sadf iostat mpstat pidstat nfsiostat-sysstat cifsiostat locales ++all: sadc sar sadf iostat tapestat mpstat pidstat nfsiostat-sysstat cifsiostat locales + + common.o: common.c version.h common.h ioconf.h sysconfig.h + +@@ -221,6 +221,10 @@ iostat.o: iostat.c iostat.h version.h co + + iostat: iostat.o librdstats.a libsyscom.a + ++tapestat.o: tapestat.c tapestat.h version.h common.h ++ ++tapestat: tapestat.o librdstats.a libsyscom.a ++ + pidstat.o: pidstat.c pidstat.h version.h common.h rd_stats.h + + pidstat: pidstat.o librdstats.a libsyscom.a +@@ -269,6 +273,8 @@ ifeq ($(INSTALL_DOC),y) + $(INSTALL_DATA) $(MANGRPARG) man/sysstat.5 $(DESTDIR)$(MAN5_DIR) + rm -f $(DESTDIR)$(MAN1_DIR)/iostat.1* + $(INSTALL_DATA) $(MANGRPARG) man/iostat.1 $(DESTDIR)$(MAN1_DIR) ++ rm -f $(DESTDIR)$(MAN1_DIR)/tapestat.1* ++ $(INSTALL_DATA) $(MANGRPARG) man/tapestat.1 $(DESTDIR)$(MAN1_DIR) + rm -f $(DESTDIR)$(MAN1_DIR)/mpstat.1* + $(INSTALL_DATA) $(MANGRPARG) man/mpstat.1 $(DESTDIR)$(MAN1_DIR) + rm -f $(DESTDIR)$(MAN1_DIR)/pidstat.1* +@@ -288,6 +294,7 @@ ifeq ($(COMPRESS_MANPG),y) + $(ZIP) $(DESTDIR)$(MAN1_DIR)/sadf.1 + $(ZIP) $(DESTDIR)$(MAN5_DIR)/sysstat.5 + $(ZIP) $(DESTDIR)$(MAN1_DIR)/iostat.1 ++ $(ZIP) $(DESTDIR)$(MAN1_DIR)/tapestat.1 + $(ZIP) $(DESTDIR)$(MAN1_DIR)/mpstat.1 + $(ZIP) $(DESTDIR)$(MAN1_DIR)/pidstat.1 + $(ZIP) $(DESTDIR)$(MAN1_DIR)/nfsiostat-sysstat.1 +@@ -328,6 +335,7 @@ endif + $(INSTALL_BIN) sar $(DESTDIR)$(BIN_DIR) + $(INSTALL_BIN) sadf $(DESTDIR)$(BIN_DIR) + $(INSTALL_BIN) iostat $(DESTDIR)$(BIN_DIR) ++ $(INSTALL_BIN) tapestat $(DESTDIR)$(BIN_DIR) + $(INSTALL_BIN) mpstat $(DESTDIR)$(BIN_DIR) + $(INSTALL_BIN) pidstat $(DESTDIR)$(BIN_DIR) + $(INSTALL_BIN) nfsiostat-sysstat $(DESTDIR)$(BIN_DIR) +@@ -395,6 +403,7 @@ ifeq ($(INSTALL_DOC),y) + rm -f $(DESTDIR)$(MAN1_DIR)/sadf.1* + rm -f $(DESTDIR)$(MAN5_DIR)/sysstat.5* + rm -f $(DESTDIR)$(MAN1_DIR)/iostat.1* ++ rm -f $(DESTDIR)$(MAN1_DIR)/tapestat.1* + rm -f $(DESTDIR)$(MAN1_DIR)/mpstat.1* + rm -f $(DESTDIR)$(MAN1_DIR)/pidstat.1* + rm -f $(DESTDIR)$(MAN1_DIR)/nfsiostat-sysstat.1* +@@ -423,6 +432,7 @@ uninstall_base: uninstall_man uninstall_ + rm -f $(DESTDIR)$(BIN_DIR)/sar + rm -f $(DESTDIR)$(BIN_DIR)/sadf + rm -f $(DESTDIR)$(BIN_DIR)/iostat ++ rm -f $(DESTDIR)$(BIN_DIR)/tapestat + rm -f $(DESTDIR)$(BIN_DIR)/mpstat + rm -f $(DESTDIR)$(BIN_DIR)/pidstat + rm -f $(DESTDIR)$(BIN_DIR)/nfsiostat-sysstat +@@ -487,7 +497,7 @@ po-files: + endif + + clean: +- rm -f sadc sar sadf iostat mpstat pidstat nfsiostat-sysstat cifsiostat *.o *.a core TAGS ++ rm -f sadc sar sadf iostat tapestat mpstat pidstat nfsiostat-sysstat cifsiostat *.o *.a core TAGS + find nls -name "*.gmo" -exec rm -f {} \; + + almost-distclean: clean nls/sysstat.pot +diff -uprN sysstat-10.1.5.orig/man/tapestat.1 sysstat-10.1.5/man/tapestat.1 +--- sysstat-10.1.5.orig/man/tapestat.1 1970-01-01 01:00:00.000000000 +0100 ++++ sysstat-10.1.5/man/tapestat.1 2016-06-01 12:46:52.028338551 +0200 +@@ -0,0 +1,216 @@ ++.TH TAPESTAT 1 "MARCH 2016" Linux "Linux User's Manual" -*- nroff -*- ++.SH NAME ++tapestat \- Report tape statistics. ++.SH SYNOPSIS ++.B tapestat [ -k | -m ] [ -t ] [ -V ] [ -y ] [ -z ] [ ++.I interval ++.B [ ++.I count ++.B ] ] ++.SH DESCRIPTION ++The ++.B tapestat ++command is used for monitoring the activity of tape drives connected to a system. ++ ++The first report generated by the ++.B tapestat ++command provides statistics ++concerning the time since the system was booted, unless the ++.B -y ++option is used, when this first report is omitted. ++Each subsequent report ++covers the time since the previous report. ++ ++The ++.I interval ++parameter specifies the amount of time in seconds between ++each report. ++The ++.I count ++parameter can be specified in conjunction with the ++.I interval ++parameter. If the ++.I count ++parameter is specified, the value of ++.I count ++determines the number of reports generated at ++.I interval ++seconds apart. If the ++.I interval ++parameter is specified without the ++.I count ++parameter, the ++.B tapestat ++command generates reports continuously. ++ ++.SH REPORT ++The ++.B tapestat ++report provides statistics for each tape drive connected to the system. ++The following data are displayed: ++ ++.B r/s ++.RS ++The number of reads issued expressed as the number per second averaged over the interval. ++ ++.RE ++.B w/s ++.RS ++The number of writes issued expressed as the number per second averaged over the interval. ++ ++.RE ++.B kB_read/s | MB_read/s ++.RS ++The amount of data read expressed in kilobytes (by default or if option -k used) or ++megabytes (if option -m used) per second averaged over the interval. ++ ++.RE ++.B kB_wrtn/s | MB_wrtn/s ++.RS ++The amount of data written expressed in kilobytes (by default or if option -k used) or ++megabytes (if option -m used) per second averaged over the interval. ++ ++.RE ++.B %Rd ++.RS ++Read percentage wait - The percentage of time over the interval spent waiting for read requests ++to complete. ++The time is measured from when the request is dispatched to the SCSI mid-layer until it signals ++that it completed. ++ ++.RE ++.B %Wr ++.RS ++Write percentage wait - The percentage of time over the interval spent waiting for write requests ++to complete. The time is measured from when the request is dispatched to the SCSI mid-layer until ++it signals that it completed. ++ ++.RE ++.B %Oa ++.RS ++Overall percentage wait - The percentage of time over the interval spent waiting for any ++I/O request to complete (read, write, and other). ++ ++.RE ++.B Rs/s ++.RS ++The number of I/Os, expressed as the number per second averaged over the interval, where ++a non-zero residual value was encountered. ++ ++.RE ++.B Ot/s ++.RS ++The number of I/Os, expressed as the number per second averaged over the interval, that ++were included as "other". Other I/O includes ioctl calls made to the tape driver and ++implicit operations performed by the tape driver such as rewind on close ++(for tape devices that implement rewind on close). It does not include any I/O performed ++using methods outside of the tape driver (e.g. via sg ioctls). ++.RE ++.RE ++.SH OPTIONS ++.IP -k ++Show the amount of data written or read in kilobytes per second instead of megabytes. ++This option is mutually exclusive with -m. ++.IP -m ++Show the amount of data written or read in megabytes per second instead of kilobytes. ++This option is mutually exclusive with -k. ++.IP -t ++Display time stamps. The time stamp format may depend ++on the value of the S_TIME_FORMAT environment variable (see below). ++.IP -V ++Print version and exit. ++.IP -y ++Omit the initial statistic showing values since boot. ++.IP -z ++Tell ++.B tapestat ++to omit output for any tapes for which there was no activity ++during the sample period. ++ ++.SH CONSIDERATIONS ++It is possible for a percentage value (read, write, or other) to be greater than 100 percent ++(the ++.B tapestat ++command will never show a percentage value more than 999). ++If rewinding a tape takes 40 seconds where the interval time is 5 seconds the %Oa value ++would show as 0 in the intervals before the rewind completed and then show as approximately ++800 percent when the rewind completes. ++ ++Similar values will be observed for %Rd and %Wr if a tape drive stops reading or writing ++and then restarts (that is it stopped streaming). In such a case you may see the r/s or w/s drop to zero and the %Rd/%Wr value could be higher than 100 when reading or writing continues ++(depending on how long it takes to restart writing or reading). ++This is only an issue if it happens a lot as it may cause tape wear and will impact ++on the backup times. ++ ++For fast tape drives you may see low percentage wait times. ++This does not indicate an issue with the tape drive. For a slower tape drive (e.g. an older ++generation DDS drive) the speed of the tape (and tape drive) is much slower than filesystem I/O, ++percent wait times are likely to be higher. For faster tape drives (e.g. LTO) the percentage ++wait times are likely to be lower as program writing to or reading from tape is going ++to be doing a lot more filesystem I/O because of the higher throughput. ++ ++Although tape statistics are implemented in the kernel using atomic variables they cannot be ++read atomically as a group. All of the statistics values are read from different files under ++/sys, because of this there may be I/O completions while reading the different files for the ++one tape drive. This may result in a set of statistics for a device that contain some values ++before an I/O completed and some after. ++ ++This command uses rounding down as the rounding method when calculating per second statistics. ++If, for example, you are using dd to copy one tape to another and running ++.B tapestat ++with an interval of 5 seconds and over the interval there were 3210 writes and 3209 reads ++then w/s would show 642 and r/s 641 (641.8 rounded down to 641). In such a case if it was ++a tar archive being copied (with a 10k block size) you would also see a difference between ++the kB_read/s and kB_wrtn/s of 2 (one I/O 10k in size divided by the interval period of 5 ++seconds). If instead there were 3210 writes and 3211 reads both w/s and r/s would both show ++642 but you would still see a difference between the kB_read/s and kB_wrtn/s values of 2 kB/s. ++ ++This command is provided with an interval in seconds. However internally the interval is ++tracked per device and can potentially have an effect on the per second statistics reported. ++The time each set of statistics is captured is kept with those statistics. The difference ++between the current and previous time is converted to milliseconds for use in calculations. ++We can look at how this can impact the statistics reported if we use an example of a tar ++archive being copied between two tape drives using dd. If both devices reported 28900 kilobytes ++transferred and the reading tape drive had an interval of 5001 milliseconds and the writing ++tape drive 5000 milliseconds that would calculate out as 5778 kB_read/s and 5780 kB_wrtn/s. ++ ++The impact of some retrieving statistics during an I/O completion, rounding down, and small differences in the interval period on the statistics calculated should be minimal but may be non-zero. ++.SH ENVIRONMENT ++The ++.B tapestat ++command takes into account the following environment variable: ++ ++.IP S_TIME_FORMAT ++If this variable exists and its value is ++.BR ISO ++then the current locale will be ignored when printing the date in the report ++header. The ++.B tapestat ++command will use the ISO 8601 format (YYYY-MM-DD) instead. ++The timestamp displayed with option -t will also be compliant with ISO 8601 ++format. ++ ++.SH BUGS ++.I /sys ++filesystem must be mounted for ++.B tapestat ++to work. It will not work on kernels that do not have sysfs support ++ ++This command requires kernel version 4.2 or later ++(or tape statistics support backported for an earlier kernel version). ++ ++.SH FILES ++.I /sys/class/scsi_tape/st/stats/* ++Statistics files for tape devices. ++ ++.I /proc/uptime ++contains system uptime. ++.SH AUTHOR ++Initial revision by Shane M. SEYMOUR (shane.seymour hpe.com) ++.br ++Modified for sysstat by Sebastien Godard (sysstat orange.fr) ++.SH SEE ALSO ++.BR iostat (1), ++.BR mpstat (1) ++ ++.I http://pagesperso-orange.fr/sebastien.godard/ +diff -uprN sysstat-10.1.5.orig/tapestat.c sysstat-10.1.5/tapestat.c +--- sysstat-10.1.5.orig/tapestat.c 1970-01-01 01:00:00.000000000 +0100 ++++ sysstat-10.1.5/tapestat.c 2016-06-01 12:54:20.384015957 +0200 +@@ -0,0 +1,697 @@ ++/* ++ * tapestat: report tape statistics ++ * (C) 2015 Hewlett-Packard Development Company, L.P. ++ * ++ * Initial revision by Shane M. SEYMOUR (shane.seymour hpe.com) ++ * Modified for sysstat by Sebastien GODARD (sysstat orange.fr) ++ * ++ *************************************************************************** ++ * This program is free software; you can redistribute it and/or modify it * ++ * under the terms of the GNU General Public License as published by the * ++ * Free Software Foundation; either version 2 of the License, or (at your * ++ * option) any later version. * ++ * * ++ * This program is distributed in the hope that it will be useful, but * ++ * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY * ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * ++ * for more details. * ++ * * ++ * You should have received a copy of the GNU General Public License along * ++ * with this program; if not, write to the Free Software Foundation, Inc., * ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA * ++ *************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#define __DO_NOT_DEFINE_COMPILE ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#undef HZ /* sys/param.h defines HZ but needed for MAXPATHLEN */ ++ ++#include "version.h" ++#include "tapestat.h" ++#include "common.h" ++ ++#ifdef USE_NLS ++#include ++#include ++#define _(string) gettext(string) ++#else ++#define _(string) (string) ++#endif ++ ++#define SCCSID "@(#)sysstat-" VERSION ": " __FILE__ " compiled " __DATE__ " " __TIME__ ++char *sccsid(void) { return (SCCSID); } ++ ++int cpu_nr = 0; /* Nb of processors on the machine */ ++int flags = 0; /* Flag for common options and system state */ ++ ++long interval = 0; ++char timestamp[64]; ++ ++struct sigaction alrm_act; ++ ++/* ++ * For tape stats - it would be extremely rare for there to be a very large ++ * number of tape drives attached to a system. I wouldn't expect to see more ++ * than 20-30 in a very large configuration and discontinguous ones should ++ * be even more rare. Because of this we keep the old and new data in a ++ * simple data structure with the tape index being the number after the tape ++ * drive, st0 at index 0, etc. ++ */ ++int max_tape_drives = 0; ++struct tape_stats *tape_new_stats = { NULL }; ++struct tape_stats *tape_old_stats = { NULL }; ++regex_t tape_reg; ++ ++/* ++ *************************************************************************** ++ * Print usage and exit. ++ * ++ * IN: ++ * @progname Name of sysstat command. ++ *************************************************************************** ++ */ ++void usage(char *progname) ++{ ++ fprintf(stderr, _("Usage: %s [ options ] [ [ ] ]\n"), ++ progname); ++ fprintf(stderr, _("Options are:\n" ++ "[ -k | -m ] [ -t ] [ -V ] [ -y ] [ -z ]\n")); ++ exit(1); ++} ++ ++/* ++ *************************************************************************** ++ * SIGALRM signal handler. No need to reset the handler here. ++ * ++ * IN: ++ * @sig Signal number. ++ *************************************************************************** ++ */ ++void alarm_handler(int sig) ++{ ++ alarm(interval); ++} ++ ++/* ++ *************************************************************************** ++ * Initialization. ++ *************************************************************************** ++ */ ++void tape_initialise(void) ++{ ++ /* How many processors on this machine? */ ++ cpu_nr = get_cpu_nr(~0); ++ ++ /* Compile regular expression for tape names */ ++ if (regcomp(&tape_reg, "^st[0-9]+$", REG_EXTENDED) != 0) { ++ exit(1); ++ } ++} ++ ++/* ++ *************************************************************************** ++ * Free structures. ++ *************************************************************************** ++ */ ++void tape_uninitialise(void) ++{ ++ regfree(&tape_reg); ++ if (tape_old_stats != NULL) { ++ free(tape_old_stats); ++ } ++ if (tape_new_stats != NULL) { ++ free(tape_new_stats); ++ } ++} ++ ++/* ++ *************************************************************************** ++ * Get maximum number of tapes in the system. ++ * ++ * RETURNS: ++ * Number of tapes found. ++ *************************************************************************** ++ */ ++int get_max_tape_drives(void) ++{ ++ DIR *dir; ++ struct dirent *entry; ++ int new_max_tape_drives, tmp, num_stats_dir = 0; ++ regmatch_t match; ++ char stats_dir[MAXPATHLEN + 1]; ++ struct stat stat_buf; ++ ++ new_max_tape_drives = max_tape_drives; ++ ++ /* Open sysfs tree */ ++ dir = opendir(SYSFS_CLASS_TAPE_DIR); ++ if (dir == NULL) ++ return 0; ++ ++ while ((entry = readdir(dir)) != NULL) { ++ if (regexec(&tape_reg, &entry->d_name[0], 1, &match, 0) == 0) { ++ /* d_name[2] to skip the st at the front */ ++ tmp = atoi(&entry->d_name[2]) + 1; ++ if (tmp > new_max_tape_drives) { ++ new_max_tape_drives = tmp; ++ } ++ } ++ snprintf(stats_dir, MAXPATHLEN, "%s/%s/%s", ++ SYSFS_CLASS_TAPE_DIR, &entry->d_name[0], "stats"); ++ if (stat(stats_dir, &stat_buf) == 0) { ++ if (S_ISDIR(stat_buf.st_mode)) { ++ num_stats_dir++; ++ } ++ } ++ } ++ closedir(dir); ++ ++ /* If there are no stats directories make the new number of tape drives 0 */ ++ if (num_stats_dir == 0) { ++ new_max_tape_drives = 0; ++ } ++ ++ return new_max_tape_drives; ++} ++ ++/* ++ *************************************************************************** ++ * Check if new tapes have been added and reallocate structures accordingly. ++ *************************************************************************** ++ */ ++void tape_check_tapes_and_realloc(void) ++{ ++ int new_max_tape_drives, i; ++ ++ /* Count again number of tapes */ ++ new_max_tape_drives = get_max_tape_drives(); ++ ++ if (new_max_tape_drives > max_tape_drives && new_max_tape_drives > 0) { ++ /* New tapes found: Realloc structures */ ++ struct tape_stats *tape_old_stats_t = (struct tape_stats *) ++ realloc(tape_old_stats, sizeof(struct tape_stats) * new_max_tape_drives); ++ struct tape_stats *tape_new_stats_t = (struct tape_stats *) ++ realloc(tape_new_stats, sizeof(struct tape_stats) * new_max_tape_drives); ++ if ((tape_old_stats_t == NULL) || (tape_new_stats_t == NULL)) { ++ if (tape_old_stats_t != NULL) { ++ free(tape_old_stats_t); ++ tape_old_stats_t = NULL; ++ } else { ++ free(tape_old_stats); ++ tape_old_stats = NULL; ++ } ++ if (tape_new_stats_t != NULL) { ++ free(tape_new_stats_t); ++ tape_new_stats_t = NULL; ++ } else { ++ free(tape_new_stats); ++ tape_new_stats = NULL; ++ } ++ ++ perror("realloc"); ++ exit(4); ++ } ++ ++ tape_old_stats = tape_old_stats_t; ++ tape_new_stats = tape_new_stats_t; ++ ++ for (i = max_tape_drives; i < new_max_tape_drives; i++) { ++ tape_old_stats[i].valid = TAPE_STATS_INVALID; ++ tape_new_stats[i].valid = TAPE_STATS_INVALID; ++ } ++ max_tape_drives = new_max_tape_drives; ++ } ++} ++ ++/* ++ *************************************************************************** ++ * Collect initial statistics for all existing tapes in the system. ++ * This function should be called only once. ++ *************************************************************************** ++ */ ++void tape_gather_initial_stats(void) ++{ ++ int new_max_tape_drives, i; ++ FILE *fp; ++ char filename[MAXPATHLEN + 1]; ++ ++ /* Get number of tapes in the system */ ++ new_max_tape_drives = get_max_tape_drives(); ++ ++ if (new_max_tape_drives == 0) { ++ /* No tapes found */ ++ fprintf(stderr, _("No tape drives with statistics found\n")); ++ exit(1); ++ } ++ else { ++ /* Allocate structures */ ++ if (tape_old_stats == NULL) { ++ tape_old_stats = (struct tape_stats *) ++ malloc(sizeof(struct tape_stats) * new_max_tape_drives); ++ tape_new_stats = (struct tape_stats *) ++ malloc(sizeof(struct tape_stats) * new_max_tape_drives); ++ for (i = 0; i < new_max_tape_drives; i++) { ++ tape_old_stats[i].valid = TAPE_STATS_INVALID; ++ tape_new_stats[i].valid = TAPE_STATS_INVALID; ++ } ++ max_tape_drives = new_max_tape_drives; ++ } else ++ /* This should only be called once */ ++ return; ++ } ++ ++ /* Read stats for each tape */ ++ for (i = 0; i < max_tape_drives; i++) { ++ /* ++ * Everything starts out valid but failing to open ++ * a file gets the tape drive marked invalid. ++ */ ++ tape_new_stats[i].valid = TAPE_STATS_VALID; ++ tape_old_stats[i].valid = TAPE_STATS_VALID; ++ ++ gettimeofday(&tape_old_stats[i].tv, NULL); ++ ++ tape_new_stats[i].tv.tv_sec = tape_old_stats[i].tv.tv_sec; ++ tape_new_stats[i].tv.tv_usec = tape_old_stats[i].tv.tv_usec; ++ ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "read_ns", read_time) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "write_ns", write_time) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "io_ns", other_time) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "read_byte_cnt", read_bytes) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "write_byte_cnt", write_bytes) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "read_cnt", read_count) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "write_cnt", write_count) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "other_cnt", other_count) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "resid_cnt", resid_count) ++ ++ tape_old_stats[i].read_time = 0; ++ tape_old_stats[i].write_time = 0; ++ tape_old_stats[i].other_time = 0; ++ tape_old_stats[i].read_bytes = 0; ++ tape_old_stats[i].write_bytes = 0; ++ tape_old_stats[i].read_count = 0; ++ tape_old_stats[i].write_count = 0; ++ tape_old_stats[i].other_count = 0; ++ tape_old_stats[i].resid_count = 0; ++ } ++} ++ ++/* ++ *************************************************************************** ++ * Collect a new sample of statistics for all existing tapes in the system. ++ *************************************************************************** ++ */ ++void tape_get_updated_stats(void) ++{ ++ int i; ++ FILE *fp; ++ char filename[MAXPATHLEN + 1] = { 0 }; ++ ++ /* Check tapes and realloc structures if needed */ ++ tape_check_tapes_and_realloc(); ++ ++ for (i = 0; i < max_tape_drives; i++) { ++ /* ++ * Everything starts out valid but failing ++ * to open a file gets the tape drive marked invalid. ++ */ ++ tape_new_stats[i].valid = TAPE_STATS_VALID; ++ gettimeofday(&tape_new_stats[i].tv, NULL); ++ ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "read_ns", read_time) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "write_ns", write_time) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "io_ns", other_time) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "read_byte_cnt", read_bytes) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "write_byte_cnt", write_bytes) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "read_cnt", read_count) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "write_cnt", write_count) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "other_cnt", other_count) ++ TAPE_STAT_FILE_VAL(TAPE_STAT_PATH "resid_cnt", resid_count) ++ ++ if ((tape_new_stats[i].read_time < tape_old_stats[i].read_time) || ++ (tape_new_stats[i].write_time < tape_old_stats[i].write_time) || ++ (tape_new_stats[i].other_time < tape_old_stats[i].other_time)) { ++ tape_new_stats[i].valid = TAPE_STATS_INVALID; ++ } ++ } ++} ++ ++/* ++ *************************************************************************** ++ * Display tapes statistics headings. ++ *************************************************************************** ++ */ ++void tape_write_headings(void) ++{ ++ printf("Tape: r/s w/s "); ++ if (DISPLAY_MEGABYTES(flags)) { ++ printf("MB_read/s MB_wrtn/s"); ++ } else { ++ printf("kB_read/s kB_wrtn/s"); ++ } ++ printf(" %%Rd %%Wr %%Oa Rs/s Ot/s\n"); ++} ++ ++/* ++ *************************************************************************** ++ * Calculate statistics for current tape. ++ * ++ * IN: ++ * @i Index in array for current tape. ++ * ++ * OUT: ++ * @stats Statistics for current tape. ++ *************************************************************************** ++ */ ++void tape_calc_one_stats(struct calc_stats *stats, int i) ++{ ++ uint64_t duration; ++ double temp; ++ FILE *fp; ++ ++ /* Duration in ms done in ms to prevent rounding issues with using seconds */ ++ duration = (tape_new_stats[i].tv.tv_sec - ++ tape_old_stats[i].tv.tv_sec) * 1000; ++ duration -= tape_old_stats[i].tv.tv_usec / 1000; ++ duration += tape_new_stats[i].tv.tv_usec / 1000; ++ ++ /* If duration is zero we need to calculate the ms since boot time */ ++ if (duration == 0) { ++ fp = fopen("/proc/uptime", "r"); ++ ++ /* ++ * Get uptime from /proc/uptime and if we can't then just set duration to ++ * be 0 - it will mean that we don't calculate stats. ++ */ ++ if (fp == NULL) { ++ duration = 0; ++ } else { ++ if (fscanf(fp, "%lf", &temp) != 1) { ++ temp = 0; ++ } ++ duration = (uint64_t) (temp * 1000); ++ fclose(fp); ++ } ++ } ++ ++ /* The second value passed into the macro is the thing being calculated */ ++ CALC_STAT_CNT(read_count, reads_per_second) ++ CALC_STAT_CNT(write_count, writes_per_second) ++ CALC_STAT_CNT(other_count, other_per_second) ++ CALC_STAT_KB(read_bytes, kbytes_read_per_second) ++ CALC_STAT_KB(write_bytes, kbytes_written_per_second) ++ CALC_STAT_PCT(read_time, read_pct_wait) ++ CALC_STAT_PCT(write_time, write_pct_wait) ++ CALC_STAT_PCT(other_time, all_pct_wait) ++ CALC_STAT_CNT(resid_count, resids_per_second) ++} ++ ++/* ++ *************************************************************************** ++ * Display statistics for current tape. ++ * ++ * IN: ++ * @tape Statistics for current tape. ++ * @i Index in array for current tape. ++ *************************************************************************** ++ */ ++void tape_write_stats(struct calc_stats *tape, int i) ++{ ++ char buffer[32]; ++ uint64_t divisor = 1; ++ ++ if (DISPLAY_MEGABYTES(flags)) ++ divisor = 1024; ++ ++ sprintf(buffer, "st%i ", i); ++ buffer[5] = 0; ++ printf("%s%7"PRId64" %7"PRId64" %11"PRId64 ++ " %11"PRId64" %3"PRId64" %3"PRId64" %3"PRId64 ++ " %7"PRId64" %7"PRId64"\n", buffer, ++ tape->reads_per_second, tape->writes_per_second, ++ tape->kbytes_read_per_second / divisor, ++ tape->kbytes_written_per_second / divisor, ++ tape->read_pct_wait, tape->write_pct_wait, ++ tape->all_pct_wait, tape->resids_per_second, ++ tape->other_per_second); ++} ++ ++/* ++ *************************************************************************** ++ * Print everything now (stats and uptime). ++ * ++ * IN: ++ * @rectime Current date and time. ++ *************************************************************************** ++ */ ++void write_stats(struct tm *rectime) ++{ ++ int i; ++ struct calc_stats tape; ++ struct tape_stats *tmp; ++ ++ /* Test stdout */ ++ TEST_STDOUT(STDOUT_FILENO); ++ ++ /* Print time stamp */ ++ if (DISPLAY_TIMESTAMP(flags)) { ++ if (DISPLAY_ISO(flags)) { ++ strftime(timestamp, sizeof(timestamp), "%FT%T%z", rectime); ++ } ++ else { ++ strftime(timestamp, sizeof(timestamp), "%x %X", rectime); ++ } ++ printf("%s\n", timestamp); ++ } ++ ++ /* Print the headings */ ++ tape_write_headings(); ++ ++ /* ++ * If either new or old is invalid or the I/Os per second is 0 and ++ * zero omit is true then we print nothing. ++ */ ++ if (max_tape_drives > 0) { ++ ++ for (i = 0; i < max_tape_drives; i++) { ++ if ((tape_new_stats[i].valid == TAPE_STATS_VALID) && ++ (tape_old_stats[i].valid == TAPE_STATS_VALID)) { ++ tape_calc_one_stats(&tape, i); ++ if (!(DISPLAY_ZERO_OMIT(flags) ++ && (tape.other_per_second == 0) ++ && (tape.reads_per_second == 0) ++ && (tape.writes_per_second == 0) ++ && (tape.kbytes_read_per_second == 0) ++ && (tape.kbytes_written_per_second == 0) ++ && (tape.read_pct_wait == 0) ++ && (tape.write_pct_wait == 0) ++ && (tape.all_pct_wait == 0) ++ && (tape.resids_per_second == 0))) { ++ tape_write_stats(&tape, i); ++ } ++ } ++ } ++ /* ++ * Swap new and old so next time we compare against the new old stats. ++ * If a new tape drive appears it won't appear in the output until after ++ * the second time we gather information about it. ++ */ ++ tmp = tape_old_stats; ++ tape_old_stats = tape_new_stats; ++ tape_new_stats = tmp; ++ } ++ printf("\n"); ++} ++ ++/* ++ *************************************************************************** ++ * Main loop: Read tape stats from the relevant sources and display them. ++ * ++ * IN: ++ * @count Number of lines of stats to print. ++ * @rectime Current date and time. ++ *************************************************************************** ++ */ ++void rw_tape_stat_loop(long int count, struct tm *rectime) ++{ ++ struct tape_stats *tmp; ++ int skip = 0; ++ ++ /* Should we skip first report? */ ++ if (DISPLAY_OMIT_SINCE_BOOT(flags) && interval > 0) { ++ skip = 1; ++ } ++ ++ /* Don't buffer data if redirected to a pipe */ ++ setbuf(stdout, NULL); ++ ++ do { ++ ++ if (tape_new_stats == NULL) { ++ tape_gather_initial_stats(); ++ } else { ++ tape_get_updated_stats(); ++ } ++ ++ /* Get time */ ++ get_localtime(rectime, 0); ++ ++ /* Check whether we should skip first report */ ++ if (!skip) { ++ /* Print results */ ++ write_stats(rectime); ++ ++ if (count > 0) { ++ count--; ++ } ++ } ++ else { ++ skip = 0; ++ tmp = tape_old_stats; ++ tape_old_stats = tape_new_stats; ++ tape_new_stats = tmp; ++ } ++ ++ if (count) { ++ pause(); ++ } ++ } ++ while (count); ++} ++ ++/* ++ *************************************************************************** ++ * Main entry to the tapestat program. ++ *************************************************************************** ++ */ ++int main(int argc, char **argv) ++{ ++ int it = 0; ++ int opt = 1; ++ int i; ++ long count = 1; ++ struct utsname header; ++ struct tm rectime; ++ ++#ifdef USE_NLS ++ /* Init National Language Support */ ++ init_nls(); ++#endif ++ ++ /* Get HZ */ ++ get_HZ(); ++ ++ /* Process args... */ ++ while (opt < argc) { ++ if (!strncmp(argv[opt], "-", 1)) { ++ for (i = 1; *(argv[opt] + i); i++) { ++ ++ switch (*(argv[opt] + i)) { ++ ++ case 'k': ++ if (DISPLAY_MEGABYTES(flags)) { ++ usage(argv[0]); ++ } ++ /* Display stats in kB/s */ ++ flags |= T_D_KILOBYTES; ++ break; ++ ++ case 'm': ++ if (DISPLAY_KILOBYTES(flags)) { ++ usage(argv[0]); ++ } ++ /* Display stats in MB/s */ ++ flags |= T_D_MEGABYTES; ++ break; ++ ++ case 't': ++ /* Display timestamp */ ++ flags |= T_D_TIMESTAMP; ++ break; ++ ++ case 'y': ++ /* Don't display stats since system restart */ ++ flags |= T_D_OMIT_SINCE_BOOT; ++ break; ++ ++ case 'z': ++ /* Omit output for devices with no activity */ ++ flags |= T_D_ZERO_OMIT; ++ break; ++ ++ case 'V': ++ /* Print version number and exit */ ++ print_version(); ++ break; ++ ++ default: ++ usage(argv[0]); ++ } ++ } ++ opt++; ++ } ++ ++ else if (!it) { ++ interval = atol(argv[opt++]); ++ if (interval < 0) { ++ usage(argv[0]); ++ } ++ count = -1; ++ it = 1; ++ } ++ ++ else if (it > 0) { ++ count = atol(argv[opt++]); ++ if ((count < 1) || !interval) { ++ usage(argv[0]); ++ } ++ it = -1; ++ } ++ else { ++ usage(argv[0]); ++ } ++ } ++ ++ if (!interval) { ++ count = 1; ++ } ++ ++ tape_initialise(); ++ ++ get_localtime(&rectime, 0); ++ ++ /* Get system name, release number and hostname */ ++ uname(&header); ++ if (print_gal_header(&rectime, header.sysname, header.release, ++ header.nodename, header.machine, cpu_nr)) { ++ flags |= T_D_ISO; ++ } ++ printf("\n"); ++ ++ /* Set a handler for SIGALRM */ ++ memset(&alrm_act, 0, sizeof(alrm_act)); ++ alrm_act.sa_handler = alarm_handler; ++ sigaction(SIGALRM, &alrm_act, NULL); ++ alarm(interval); ++ ++ /* Main loop */ ++ rw_tape_stat_loop(count, &rectime); ++ ++ /* Free structures */ ++ tape_uninitialise(); ++ ++ return 0; ++} +diff -uprN sysstat-10.1.5.orig/tapestat.h sysstat-10.1.5/tapestat.h +--- sysstat-10.1.5.orig/tapestat.h 1970-01-01 01:00:00.000000000 +0100 ++++ sysstat-10.1.5/tapestat.h 2016-06-01 12:46:52.028338551 +0200 +@@ -0,0 +1,126 @@ ++/* ++ * tapestat: report tape statistics ++ * (C) 2015 Hewlett-Packard Development Company, L.P. ++ * ++ * Initial revision by Shane M. SEYMOUR (shane.seymour hpe.com) ++ * Modified for sysstat by Sebastien GODARD (sysstat orange.fr) ++ */ ++ ++#ifndef _TAPESTAT_H ++#define _TAPESTAT_H ++ ++/* T_: tapestat - D_: Display - F_: Flag */ ++#define T_D_TIMESTAMP 0x00001 ++#define T_D_KILOBYTES 0x00002 ++#define T_D_MEGABYTES 0x00004 ++#define T_D_OMIT_SINCE_BOOT 0x00008 ++#define T_D_ISO 0x00010 ++#define T_D_ZERO_OMIT 0x00020 ++ ++#define DISPLAY_TIMESTAMP(m) (((m) & T_D_TIMESTAMP) == T_D_TIMESTAMP) ++#define DISPLAY_KILOBYTES(m) (((m) & T_D_KILOBYTES) == T_D_KILOBYTES) ++#define DISPLAY_MEGABYTES(m) (((m) & T_D_MEGABYTES) == T_D_MEGABYTES) ++#define DISPLAY_OMIT_SINCE_BOOT(m) (((m) & T_D_OMIT_SINCE_BOOT) == T_D_OMIT_SINCE_BOOT) ++#define DISPLAY_ISO(m) (((m) & T_D_ISO) == T_D_ISO) ++#define DISPLAY_ZERO_OMIT(m) (((m) & T_D_ZERO_OMIT) == T_D_ZERO_OMIT) ++ ++ ++#define TAPE_STATS_VALID 1 ++#define TAPE_STATS_INVALID 0 ++ ++#define SYSFS_CLASS_TAPE_DIR "/sys/class/scsi_tape" ++#define TAPE_STAT_PATH "/sys/class/scsi_tape/st%i/stats/" ++ ++#define TAPE_STAT_FILE_VAL(A, B) \ ++ snprintf(filename, MAXPATHLEN, A, i); \ ++ if ((fp = fopen(filename, "r")) != NULL) { \ ++ if (fscanf(fp, "%"PRId64, &tape_new_stats[i].B) != 1) { \ ++ tape_new_stats[i].valid = TAPE_STATS_INVALID; \ ++ } \ ++ fclose(fp); \ ++ } else { \ ++ tape_new_stats[i].valid = TAPE_STATS_INVALID; \ ++ continue; \ ++ } ++ ++ ++/* ++ * A - tape_stats structure member name, e.g. read_count ++ * B - calc_stats structure member name, e.g. reads_per_second ++ * ++ * These macros are not selfcontained they depend on some other ++ * variables defined either as global or local to the function. ++ */ ++ ++#define CALC_STAT_CNT(A, B) \ ++ if ((tape_new_stats[i].A == tape_old_stats[i].A) || \ ++ (duration <= 0)) { \ ++ stats->B = 0; \ ++ } else { \ ++ temp = (double) (tape_new_stats[i].A - \ ++ tape_old_stats[i].A) \ ++ / (((double) duration) / 1000); \ ++ stats->B = (uint64_t) temp; \ ++ } ++#define CALC_STAT_KB(A, B) \ ++ if ((tape_new_stats[i].A == tape_old_stats[i].A) || \ ++ (duration <= 0)) { \ ++ stats->B = 0; \ ++ } else { \ ++ temp = (double) (tape_new_stats[i].A - \ ++ tape_old_stats[i].A) \ ++ / (((double) duration) / 1000.0); \ ++ stats->B = (uint64_t) (temp / 1024.0); \ ++ } ++ ++#define TAPE_MAX_PCT 999 ++ ++#define CALC_STAT_PCT(A, B) \ ++ if ((tape_new_stats[i].A == tape_old_stats[i].A) || \ ++ (duration <= 0)) { \ ++ stats->B = 0; \ ++ } else { \ ++ temp = (double) (tape_new_stats[i].A - \ ++ tape_old_stats[i].A) \ ++ / (((double) duration)); \ ++ stats->B = (uint64_t) (100.0 * temp / 1000000.0); \ ++ if (stats->B > TAPE_MAX_PCT) \ ++ stats->B = TAPE_MAX_PCT; \ ++ } ++ ++struct tape_stats { ++ uint64_t read_time; ++ uint64_t write_time; ++ uint64_t other_time; ++ uint64_t read_bytes; ++ uint64_t write_bytes; ++ uint64_t read_count; ++ uint64_t write_count; ++ uint64_t other_count; ++ uint64_t resid_count; ++ char valid; ++ struct timeval tv; ++}; ++struct calc_stats { ++ uint64_t reads_per_second; ++ uint64_t writes_per_second; ++ uint64_t other_per_second; ++ uint64_t kbytes_read_per_second; ++ uint64_t kbytes_written_per_second; ++ uint64_t read_pct_wait; ++ uint64_t write_pct_wait; ++ uint64_t all_pct_wait; ++ uint64_t resids_per_second; ++}; ++ ++void tape_get_updated_stats(void); ++void tape_gather_initial_stats(void); ++void tape_check_tapes_and_realloc(void); ++int get_max_tape_drives(void); ++void tape_uninitialise(void); ++void tape_initialise(void); ++void tape_calc_one_stats(struct calc_stats *, int); ++void tape_write_headings(void); ++void tape_write_stats(struct calc_stats *, int); ++ ++#endif /* _TAPESTAT_H */ diff --git a/SOURCES/sysstat-10.1.5-zip-conf.patch b/SOURCES/sysstat-10.1.5-zip-conf.patch new file mode 100644 index 0000000..7e4f7e3 --- /dev/null +++ b/SOURCES/sysstat-10.1.5-zip-conf.patch @@ -0,0 +1,10 @@ +diff -ur sysstat-10.1.5.orig/sysstat.sysconfig.in sysstat-10.1.5/sysstat.sysconfig.in +--- sysstat-10.1.5.orig/sysstat.sysconfig.in 2012-05-13 15:00:39.000000000 +0200 ++++ sysstat-10.1.5/sysstat.sysconfig.in 2014-09-01 23:08:48.412640491 +0200 +@@ -12,3 +12,6 @@ + # which are used for the generation of log files. + SADC_OPTIONS="@COLLECT_ALL@" + ++# Compression program to use. ++ZIP="@ZIP@" ++ diff --git a/SPECS/sysstat.spec b/SPECS/sysstat.spec new file mode 100644 index 0000000..fe0d710 --- /dev/null +++ b/SPECS/sysstat.spec @@ -0,0 +1,674 @@ +Summary: Collection of performance monitoring tools for Linux +Name: sysstat +Version: 10.1.5 +Release: 13%{?dist} +License: GPLv2+ +Group: Applications/System +URL: http://sebastien.godard.pagesperso-orange.fr/ +Source: http://pagesperso-orange.fr/sebastien.godard/%{name}-%{version}.tar.bz2 + +Patch0: sysstat-10.0.0-makefile.patch +# fixes 1100365 +Patch1: sysstat-10.1.5-overwrite-sa.patch +# fixes 1097294 +Patch2: sysstat-10.1.5-sa2-xz.patch +# fixes 1128569 +Patch3: sysstat-10.1.5-dyn-tick.patch +# fixes 1110852 +Patch4: sysstat-10.1.5-sysstat-5.patch +# fixes 1102610 +Patch5: sysstat-10.1.5-zip-conf.patch +# fixes 1146081 +Patch6: sysstat-10.1.5-single-cpu-cifs.patch +# fixes 1162773 +Patch7: sysstat-10.1.5-elapsed-time.patch +# fixes 1224882 +Patch8: sysstat-10.1.5-pids-prealloc.patch +# fixes 1258990 +Patch9: sysstat-10.1.5-max-cpus.patch +# fixes 1267972 +Patch10: sysstat-10.1.5-max-name-len.patch +# fixes 1328490 +Patch11: sysstat-10.1.5-int-handler.patch +# fixes 846699 +Patch12: sysstat-10.1.5-nfsiostat.patch +# fixes 1332662 +Patch13: sysstat-10.1.5-tapestat.patch +# fixes 1381128 +Patch14: 0001-sar-make-buffers-that-hold-timestamps-bigger.patch +# fixes 1448489 +Patch15: 0001-pidstat-Display-stats-since-boot-time-for-a-list-of-.patch +# fixes 1440000 +Patch16: 0001-sar-Improve-cpuinfo-read-for-POWER-architecture.patch + +Requires: /etc/cron.d, fileutils, grep, sh-utils, textutils +Requires(post): systemd, systemd-sysv +Requires(preun): systemd +Requires(postun): systemd + +BuildRequires: %{_includedir}/linux/if.h, gettext, lm_sensors-devel, perl +BuildRequires: systemd + +%description +The sysstat package contains sar, sadf, mpstat, iostat, pidstat, nfsiostat-sysstat, +tapestat, cifsiostat and sa tools for Linux. +The sar command collects and reports system activity information. This +information can be saved in a file in a binary format for future inspection. The +statistics reported by sar concern I/O transfer rates, paging activity, +process-related activities, interrupts, network activity, memory and swap space +utilization, CPU utilization, kernel activities and TTY statistics, among +others. Both UP and SMP machines are fully supported. +The sadf command may be used to display data collected by sar in various formats +(CSV, XML, etc.). +The iostat command reports CPU utilization and I/O statistics for disks. +The tapestat command reports statistics for tapes connected to the system. +The mpstat command reports global and per-processor statistics. +The pidstat command reports statistics for Linux tasks (processes). +The nfsiostat-sysstat command reports I/O statistics for network file systems. +The cifsiostat command reports I/O statistics for CIFS file systems. + +%prep +%setup -q +%patch0 -p1 -b .ls +%patch1 -p1 -b .overwrite-sa +%patch2 -p1 -b .sa2-xz +%patch3 -p1 -b .dyn-tick +%patch4 -p1 -b .sysstat-5 +%patch5 -p1 -b .zip-conf +%patch6 -p1 -b .single-cpu-cifs +%patch7 -p1 -b .elapsed-time +%patch8 -p1 -b .pids-prealloc +%patch9 -p1 -b .max-cpus +%patch10 -p1 -b .max-name-len +%patch11 -p1 -b .int-handler +%patch12 -p1 -b .nfsiostat +%patch13 -p1 -b .tapestat +%patch14 -p1 -b .korean +%patch15 -p1 -b .pidstat +%patch16 -p1 -b .power + +iconv -f windows-1252 -t utf8 CREDITS > CREDITS.aux +mv CREDITS.aux CREDITS + +%build +%configure sa_lib_dir=%{_libdir}/sa history=28 compressafter=31 \ + --disable-man-group +%{__sed} -i 's/SADC_OPTIONS=""/SADC_OPTIONS="-S DISK"/' sysstat.sysconfig +CFLAGS="$RPM_OPT_FLAGS -DSADC_PATH=\\\"%{_libdir}/sa/sadc\\\"" +make CFLAGS="$CFLAGS" LFLAGS="" %{?_smp_mflags} + +%install +make install DESTDIR=%{buildroot} + +# Install cron file +mkdir -p %{buildroot}/%{_sysconfdir}/cron.d +install -m 0644 cron/sysstat.crond %{buildroot}/%{_sysconfdir}/cron.d/sysstat + +# Install service file +mkdir -p %{buildroot}%{_unitdir} +install -m 0644 sysstat.service %{buildroot}%{_unitdir}/ + +%find_lang %{name} + +%post +%systemd_post sysstat.service + +%preun +%systemd_preun sysstat.service +if [[ $1 -eq 0 ]]; then + # Remove sa logs if removing sysstat completely + rm -f %{_localstatedir}/log/sa/* +fi + +%postun +%systemd_postun sysstat.service + +%triggerun -- sysstat < 10.0.2-1 +# Save the current service runlevel info +# User must manually run systemd-sysv-convert --apply sysstat +# to migrate them to systemd targets +/usr/bin/systemd-sysv-convert --save sysstat >/dev/null 2>&1 ||: + +# Run these because the SysV package being removed won't do them +/sbin/chkconfig --del sysstat >/dev/null 2>&1 || : +/bin/systemctl try-restart sysstat.service >/dev/null 2>&1 || : + +%files -f %{name}.lang +%doc CHANGES COPYING CREDITS README FAQ +%config(noreplace) %attr(0600,-,-) %{_sysconfdir}/cron.d/sysstat +%config(noreplace) %{_sysconfdir}/sysconfig/sysstat +%config(noreplace) %{_sysconfdir}/sysconfig/sysstat.ioconf +%{_unitdir}/sysstat.service +%{_bindir}/* +%{_libdir}/sa +%{_mandir}/man1/* +%{_mandir}/man5/* +%{_mandir}/man8/* +%{_localstatedir}/log/sa + +%changelog +* Wed Nov 08 2017 Michal Sekletar - 10.1.5-13 +- fix output of pidstat -p $PID (#1448489) +- improve reading of /proc/cpuinfo on Power (#1440000) + +* Wed Mar 29 2017 Michal Sekletar - 10.1.5-12 +- sar: output timestamps when running with ko_KR.UTF-8 locale (#1381128) + +* Wed Jun 01 2016 Peter Schiffer - 10.1.5-11 +- related: #1332662 + fixed more coverity issues + +* Tue May 31 2016 Peter Schiffer - 10.1.5-10 +- related: #846699, #1332662 + fixed coverity issues + +* Thu May 05 2016 Peter Schiffer - 10.1.5-9 +- related: #846699 + do the renaming of nfsiostat properly, with patch +- resolves: #1332662 + added tapestat utility for monitoring tape drives + +* Fri Apr 29 2016 Peter Schiffer - 10.1.5-8 +- resolves: #846699 + renamed nfsiostat to nfsiostat-sysstat, as nfsiostat is also provided + by the nfs-utils package +- resolves: #1224882 + fixed bug when pidstat could run out of pre-allocated space for PIDs +- resolves: #1258990 + added support for more CPUs +- resolves: #1267972 + fixed bug when iostat didn't display the full device name if it's too long +- resolves: #1328490 + fixed bug, when sadc could forward SIGINIT to init process and couse reboot + +* Wed Nov 12 2014 Peter Schiffer - 10.1.5-7 +- resolves: #1162773 + fixed incorrect description of util field on iostat(1) and sar(1) man pages + +* Mon Sep 29 2014 Peter Schiffer - 10.1.5-6 +- resolves: #1146081 + fixed issue when cifsiostat and nfsiostat were reporting incorrect statistics + on a single CPU machines + +* Mon Sep 1 2014 Peter Schiffer - 10.1.5-5 +- resolves: #1100365 + fixed issue when sa data files weren't correctly overwritten in some cases +- resolves: #1097294 + count with xz compressed files as well in sa2 script +- resolves: #1097292 + fix file mode of sysstat cron file +- resolves: #1128569 + added workaround for dyn-tick kernel feature which makes /proc/stat file + unreliable under certain circumstances +- resolves: #1110852 + added better explanation of HISTORY setting to sysstat(5) man page +- resolves: #1102610 + added possibility to set compress method in /etc/sysconfig/sysstat file + +* Fri Jan 24 2014 Daniel Mach - 10.1.5-4 +- Mass rebuild 2014-01-24 + +* Mon Jan 6 2014 Peter Schiffer - 10.1.5-3 +- resolves: #1048902 + added missing build requires on systemd + +* Fri Dec 27 2013 Daniel Mach - 10.1.5-2 +- Mass rebuild 2013-12-27 + +* Fri Apr 5 2013 Peter Schiffer - 10.1.5-1 +- resolves: #919581 + updated to 10.1.5 +- collect disk statistics by default + +* Fri Feb 15 2013 Fedora Release Engineering - 10.1.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Wed Jan 2 2013 Peter Schiffer - 10.1.3-1 +- resolves: #890425 + updated to 10.1.3 + +* Mon Dec 3 2012 Peter Schiffer - 10.1.2-2 +- added new -y option to iostat command to skip first since boot report if + displaying multiple reports + +* Tue Nov 13 2012 Peter Schiffer - 10.1.2-1 +- resolves: #863791 + updated to 10.1.2 +- resolves: #850333 + migrated to the new systemd-rpm macros +- cleaned .spec file + +* Wed Aug 01 2012 Peter Schiffer - 10.1.1-1 +- resolves: #844387 + update to 10.1.1 +- keep log files for 28 days instead of 7 +- collect all aditional statistics + +* Sat Jul 21 2012 Fedora Release Engineering - 10.0.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Jun 19 2012 Peter Schiffer - 10.0.5-1 +- resolves: #822867 + update to 10.0.5 + +* Wed May 16 2012 Peter Schiffer - 10.0.4-1 +- resolves: #803032 + update to 10.0.4 +- resolves: #820725 + enable sysstat service by default + +* Sat Jan 14 2012 Fedora Release Engineering - 10.0.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Nov 30 2011 Peter Schiffer - 10.0.3-1 +- resolves: #757687 + update to 10.0.3 + +* Tue Sep 13 2011 Tom Callaway - 10.0.2-2 +- fix libdir pathing in systemd service file + +* Mon Sep 12 2011 Tom Callaway - 10.0.2-1 +- update to 10.0.2 +- convert to systemd + +* Tue Jun 7 2011 Ivana Hutarova Varekova - 10.0.1-1 +- update to 10.0.1 +- remove useles patches + +* Wed May 4 2011 Ivana Hutarova Varekova - 10.0.0-4 +- close the file descriptor in a special situation in read_uoptime function +- fix the number on open files in cifsiostat output + +* Mon May 2 2011 Ivana Hutarova Varekova - 10.0.0-3 +- add -h optioon to iostat tool + (-h Make the disk stats report easier to read by a human.) + +* Mon Apr 4 2011 Ivana Hutarova Varekova - 10.0.0-2 +- remove unnecessary patch + +* Mon Apr 4 2011 Ivana Hutarova Varekova - 10.0.0-1 +- update to 10.0.0 + remove obsolete patches + remove autoreconfiguration + +* Wed Feb 09 2011 Fedora Release Engineering - 9.0.6.1-14 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Mon Nov 22 2010 Ivana Hutarova Varekova - 9.0.6.1-13 +- Resolves: #642280 + sar -u overflow problem - thanks Michal Srb + +* Thu Oct 7 2010 Ivana Hutarova Varekova - 9.0.6.1-12 +- improve sar thickless kernel support + (fix the output per separate cpu "-P ALL" option ) + +* Mon Oct 4 2010 Ivana Hutarova Varekova - 9.0.6.1-11 +- resolves: #635646 + test the output of localtime properly + +* Wed Sep 29 2010 jkeating - 9.0.6.1-10 +- Rebuilt for gcc bug 634757 + +* Thu Sep 23 2010 Ivana Hutarova Varekova - 9.0.6.1-9 +- add the mandir patch +- add the possibility to sed sadc cron options + +* Tue Sep 21 2010 Ivana Hutarova Varekova - 9.0.6.1-8 +- add necessary dependency (autoconf), necessary because of patch7 + +* Tue Sep 21 2010 Ivana Hutarova Varekova - 9.0.6.1-7 +- remove needless DOCDIR setting +- remove needless INIT_DIR setting +- fix the problem with --disable-man-group option + +* Wed Sep 8 2010 Ivana Hutarova Varekova - 9.0.6.1-6 +- fix the sar output on tickless kernel + +* Fri Aug 13 2010 Ivana Hutarova Varekova - 9.0.6.1-5 +- remove bogus links description + +* Mon Jul 19 2010 Ivana Hutarova Varekova - 9.0.6.1-4 +- fix sar problem - sysstat can not monitor system status every second + +* Mon Apr 19 2010 Ivana Hutarova Varekova - 9.0.6.1-3 +- fix mpstat tool (when the cpu is switched off) + +* Fri Apr 16 2010 Ivana Hutarova Varekova - 9.0.6.1-2 +- fix the mpstat output on tickless kernel + +* Tue Mar 2 2010 Ivana Hutarova Varekova - 9.0.6.1-1 +- update to 9.0.6.1 + +* Tue Feb 16 2010 Ivana Hutarova Varekova - 9.0.6-3 +- fix init script format + +* Fri Dec 11 2009 Ivana Hutarova Varekova - 9.0.6-2 +- fix the problem in get_nfs_mount_nr function + ( iostat -n causes stack smashing) + +* Wed Dec 2 2009 Ivana Hutarva Varekova - 9.0.6-1 +- update to 9.0.6 + +* Tue Sep 15 2009 Ivana Varekova - 9.0.4-4 +- fix init script + +* Mon Sep 14 2009 Ivana Varekova - 9.0.4-3 +- fix init script - add INIT INFO flags (#522740) + and add condrestart, try-restart and force-reload (#522743) + +* Sun Jul 26 2009 Fedora Release Engineering - 9.0.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Mon Jul 20 2009 Ivana Varekova - 9.0.4-1 +- update to 9.0.4 + +* Thu May 28 2009 Ivana Varekova - 9.0.3-1 +- update to 9.0.3 +- remove obsolete patches + +* Wed Feb 25 2009 Fedora Release Engineering - 8.0.4-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Fri Dec 5 2008 Ivana Varekova - 8.0.4-6 +- add /proc/diskstats reading patch + +* Mon Sep 22 2008 Ivana Varekova - 8.0.4-5 +- Resolves: #463066 - Fix Patch0:/%%patch mismatch + +* Wed Apr 23 2008 Ivana Varekova - 8.0.4-4 +- Resolves: #442801 mpstat shows one extra cpu + thanks Chris Wright + +* Thu Mar 6 2008 Ivana Varekova - 8.0.4-3 +- add nfs extended statistic to iostat command + +* Thu Feb 28 2008 Ivana Varekova - 8.0.4-2 +- retry write functuon in sadc command - thanks Tomas Mraz + +* Fri Feb 8 2008 Ivana Varekova - 8.0.4-1 +- updated to 8.0.4 + +* Mon Dec 3 2007 Ivana Varekova - 8.0.3-1 +- updated to 8.0.3 + +* Fri Nov 9 2007 Ivana Varekova - 8.0.2-3 +- used macros instead of var, etc + +* Thu Nov 8 2007 Ivana Varekova - 8.0.2-2 +- change license tag +- remove sysstat.crond source (add -d) +- remove obsolete sysconfig file +- spec file cleanup + +* Mon Nov 5 2007 Ivana Varekova - 8.0.2-1 +- update 8.0.2 +- spec file cleanup + +* Wed Oct 24 2007 Ivana Varekova - 8.0.1-2 +- remove useless patches + +* Mon Oct 22 2007 Ivana Varekova - 8.0.1-1 +- update to 8.0.1 +- remove useless patches +- spec file cleanup +- remove smp build flag (ar problem) +- add libdir flags + +* Wed Aug 15 2007 Ivana Varekova - 7.0.4-3 +- fix cve-2007-3852 - + sysstat insecure temporary file usage + +* Fri Mar 23 2007 Ivana Varekova - 7.0.4-2 +- fix sa2 problem (sa2 works wrong when the /var/log/sa file is + a link to another directory) + +* Mon Feb 12 2007 Ivana Varekova - 7.0.4-1 +- update to 7.0.4 +- spec file cleanup + +* Tue Jan 30 2007 Ivana Varekova - 7.0.3-3 +- remove -s flag + +* Mon Dec 18 2006 Ivana Varekova - 7.0.3-1 +- update to 7.0.3 + +* Tue Nov 21 2006 Ivana Varekova - 7.0.2-3 +- update NFS mount statistic patch + +* Wed Nov 8 2006 Ivana Varekova - 7.0.2-1 +- update to 7.0.2 + +* Thu Oct 26 2006 Ivana Varekova - 7.0.0-3 +- move tmp file (#208433) + +* Mon Oct 9 2006 Ivana Varekova - 7.0.0-2 +- add NFS mount statistic (#184321) + +* Fri Jul 14 2006 Marcela Maslanova - 7.0.0-1 +- new version 7.0.0 + +* Wed Jul 12 2006 Jesse Keating - 6.0.2-2.1 +- rebuild + +* Mon Jun 5 2006 Jesse Keating 6.0.2-2 +- Add missing BR of gettext + +* Fri May 5 2006 Ivana Varekova 6.0.2-1 +- update to 6.0.2 +- remove asm/page.h used sysconf command to get PAGE_SIZE + +* Fri Feb 10 2006 Jesse Keating - 6.0.1-3.2.1 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 6.0.1-3.2 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Tue Oct 11 2005 Ivana Varekova 6.0.1-3 +- add FAQ to documentation (bug 170158) + +* Mon Oct 10 2005 Ivana Varekova 6.0.1-2 +- fix chkconfig problem + +* Fri Oct 7 2005 Ivana Varekova 6.0.1-1 +- version 6.0.1 + +* Thu Aug 18 2005 Florian La Roche +- no need to kernel kernel 2.2 or newer anymore + +* Tue May 10 2005 Ivana Varekova 5.0.5-10.fc +- add debug files to debug_package + +* Mon Mar 7 2005 Ivana Varekova 5.0.5-9.fc +- rebuilt (add gcc4fix, update lib64ini) + +* Fri Mar 4 2005 Ivana Varekova 5.0.5-7.fc +- rebuilt + +* Thu Sep 30 2004 Charles Bennett 5.0.5-5.fc +- bring in filename and append-msg patch +- append-msg adds verbose text for when saNN data file cpu count +- does not match cpu count on the currently running system + +* Wed Jun 30 2004 Nils Philippsen +- version 5.0.5 +- remove some obsolete patches +- update statreset, overrun, lib64init patches +- renumber patches + +* Wed Jun 16 2004 Alan Cox +- Fix spew of crap to console at startup +- Fix order of startup (#124035) +- Fix array overrun (#117182) +- Fix interrupt buffer sizing (caused bogus irq info) + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Wed Mar 24 2004 Justin Forbes <64bit_fedora@comcast.net> 5.0.1-2 +- fix lib64 init + +* Tue Mar 02 2004 Elliot Lee +- rebuilt + +* Wed Feb 18 2004 Nils Philippsen 5.0.1-1 +- version 5.0.1 +- update statreset patch + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Thu Jan 22 2004 Nils Philippsen 5.0.0-0.6 +- let user configure how long to keep logs through /etc/sysconfig/sysstat + (#81294) +- reset stats at system boot (#102445) + +* Wed Jan 21 2004 Nils Philippsen 5.0.0-0.5 +- fix ifnamsiz patch for s390x (hopefully) + +* Tue Jan 20 2004 Nils Philippsen 5.0.0-0.4 +- fix insecure tmp files in scripts (#78212) +- require tools needed in scripts +- use IFNAMSIZ from {_includedir}/linux/if.h for maximum interface length + +* Mon Jan 12 2004 Nils Philippsen 5.0.0-0.3 +- Buildrequires: perl +- check for %%_lib == lib64 instead of specific arches + +* Mon Jan 12 2004 Nils Philippsen 5.0.0-0.2 +- fix dealing with lib64 case of cron.d file + +* Mon Jan 12 2004 Nils Philippsen 5.0.0-0.1 +- version 5.0.0 + +* Wed Jun 04 2003 Elliot Lee +- rebuilt + +* Mon Mar 3 2003 Joe Orton 4.0.7-4 +- really fix paths for multilib (#82913) + +* Wed Feb 19 2003 Bill Nottingham 4.0.7-3 +- fix paths on multilib arches (#82913) + +* Wed Jan 22 2003 Tim Powers +- rebuilt + +* Sat Nov 23 2002 Mike A. Harris 4.0.7-1 +- Updated to new upstream version 4.0.7 + +* Tue Nov 19 2002 Mike A. Harris 4.0.5-7 +- Fixed files installed in /usr/doc to be put in correct place + +* Tue Oct 8 2002 Mike A. Harris 4.0.5-6 +- All-arch rebuild + +* Tue Jul 23 2002 Trond Eivind Glomsrød 4.0.5-3 +- Rebuild + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Mon Jun 17 2002 Trond Eivind Glomsrød 4.0.5-1 +- 4.0.5-1 +- isag is no longer installed by default upstream, removing + requirement on gnuplot + +* Thu May 23 2002 Tim Powers +- automated rebuild + +* Mon Apr 22 2002 Trond Eivind Glomsrød 4.0.4-1 +- 4.0.4 +- Add an explicit requires on gnuplot (#63474) + +* Fri Apr 12 2002 Trond Eivind Glomsrød 4.0.3-2 +- Do the daily sa2 run just before midnight, not at 4AM... you'd + only get 4 hours worth of data that way (#63132) + +* Thu Feb 28 2002 Trond Eivind Glomsrød 4.0.3-1 +- 4.0.3 + +* Wed Feb 27 2002 Trond Eivind Glomsrød 4.0.2-3 +- Rebuild + +* Wed Jan 09 2002 Tim Powers +- automated rebuild + +* Wed Dec 12 2001 Trond Eivind Glomsrød 4.0.2-1 +- 4.0.2 +- the kernel patch for extended statistics is in, don't say it needs + applying in the man page + +* Mon Aug 13 2001 Preston Brown +- be more verbose about which files are corrupt (#47122) + +* Mon Jul 2 2001 Preston Brown +- run sa1 from cron.d to fix run-parts interaction problem (#37733) + +* Fri Jun 29 2001 Preston Brown +- upgrade to 4.0.1 stable release + +* Sun Jun 24 2001 Elliot Lee +- Bump release + rebuild. + +* Sun Apr 8 2001 Preston Brown +- explicitly set safe umask (#35142) + +* Fri Mar 9 2001 Preston Brown +- iostat disk utilization was off by a factor of 10. + +* Wed Feb 14 2001 Preston Brown +- 3.3.5 brings us full support for kernel IO stats + +* Tue Jan 30 2001 Preston Brown +- Summarize previous day's activity with sa2, not current day (which is only 4 hours of data when it gets run) (#24820) +- upgrade to 3.3.4 for full 2.4 compatibility and improved iostat + +* Wed Jan 17 2001 Preston Brown +- iostat man page fixes + +* Fri Jan 05 2001 Preston Brown +- 3.3.3, crontab fixes + +* Fri Dec 29 2000 Bill Nottingham +- fix prereqs + +* Fri Oct 13 2000 Preston Brown +- crontab entry was still incorrect. Fixed. + +* Mon Oct 09 2000 Preston Brown +- make sure disk accounting is enabled to fix iostat -l, -p (#16268) +- crontab entries were missing the user (root) to run as (#18212) + +* Tue Aug 22 2000 Preston Brown +- enable IO accounting now that kernel supports it + +* Wed Aug 16 2000 Nalin Dahyabhai +- fix buildrooting (#16271) + +* Tue Aug 08 2000 Preston Brown +- bugfixes in 3.2.4 cause our inclusion. :) + +* Wed Jul 12 2000 Prospector +- automatic rebuild + +* Thu Jun 29 2000 Preston Brown +- 3.2.3 fixes SMP race condition + +* Tue Jun 20 2000 Preston Brown +- FHS macros +- 3.2.2 + +* Fri May 26 2000 Preston Brown +- packaged for Winston +- change va patch to indicate kernel is not patched for iostat accounting. + re-enable if our stock kernel gets this patch. +- upgrade to 3.2. +- install crontab entry. + +* Sun Dec 12 1999 Ian Macdonald +- upgraded to 2.2 + +* Fri Oct 29 1999 Ian Macdonald +- first RPM release (2.1)