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 */