From 8330f4dac2a05706a77ad53a4569c5897ea072e3 Mon Sep 17 00:00:00 2001 From: Sebastien GODARD Date: Sun, 18 Feb 2018 16:18:58 +0100 Subject: [PATCH] sar: Add new -z option Add new option to sar (-z). This option tells sar to omit output for any devices for which there was no activity during the sample period. This option applies for network interfaces, interrupts, block devices, serial lines, filesystems, CPU (in softnet statistics). Note: This option already existed for iostat. Signed-off-by: Sebastien GODARD --- pr_stats.c | 112 ++++++++++++++++++++++++++++++++++++++--------------- rd_stats.h | 11 ++++-- sa.h | 3 ++ sar.c | 7 +++- 4 files changed, 97 insertions(+), 36 deletions(-) diff --git a/pr_stats.c b/pr_stats.c index 567d982..90073b2 100644 --- a/pr_stats.c +++ b/pr_stats.c @@ -342,7 +342,7 @@ __print_funct_t print_irq_stats(struct activity *a, int prev, int curr, int i; struct stats_irq *sic, *sip; - if (dis) { + if (dis || DISPLAY_ZERO_OMIT(flags)) { print_hdr_line(timestamp[!curr], a, FIRST, 0, 9); } @@ -366,6 +366,9 @@ __print_funct_t print_irq_stats(struct activity *a, int prev, int curr, /* Should current interrupt (including int "sum") be displayed? */ if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) { + if (DISPLAY_ZERO_OMIT(flags) && !memcmp(sip, sic, STATS_IRQ_SIZE)) + continue; + /* Yes: Display it */ printf("%-11s", timestamp[curr]); if (!i) { @@ -950,7 +953,7 @@ __print_funct_t print_serial_stats(struct activity *a, int prev, int curr, int i, j, j0, found; struct stats_serial *ssc, *ssp; - if (dis) { + if (dis || DISPLAY_ZERO_OMIT(flags)) { print_hdr_line(timestamp[!curr], a, FIRST, 0, 9); } @@ -999,6 +1002,9 @@ __print_funct_t print_serial_stats(struct activity *a, int prev, int curr, if (!found) continue; + if (DISPLAY_ZERO_OMIT(flags) && !memcmp(ssp, ssc, STATS_SERIAL_SIZE)) + continue; + printf("%-11s", timestamp[curr]); cprintf_in(IS_INT, " %3d", "", ssc->line); @@ -1040,7 +1046,7 @@ __print_funct_t print_disk_stats(struct activity *a, int prev, int curr, unit = UNIT_KILOBYTE; } - if (dis) { + if (dis || DISPLAY_ZERO_OMIT(flags)) { print_hdr_line(timestamp[!curr], a, FIRST, DISPLAY_HUMAN_READ(flags) ? -1 : 0, 9); } @@ -1064,6 +1070,9 @@ __print_funct_t print_disk_stats(struct activity *a, int prev, int curr, sdp = (struct stats_disk *) ((char *) a->buf[prev] + j * a->msize); } + if (DISPLAY_ZERO_OMIT(flags) && !memcmp(sdp, sdc, STATS_DISK_SIZE)) + continue; + /* Compute service time, etc. */ compute_ext_disk_stats(sdc, sdp, itv, &xds); @@ -1140,7 +1149,7 @@ __print_funct_t print_net_dev_stats(struct activity *a, int prev, int curr, unit = UNIT_BYTE; } - if (dis) { + if (dis || DISPLAY_ZERO_OMIT(flags)) { print_hdr_line(timestamp[!curr], a, FIRST, DISPLAY_HUMAN_READ(flags) ? -1 : 0, 9); } @@ -1164,6 +1173,9 @@ __print_funct_t print_net_dev_stats(struct activity *a, int prev, int curr, sndp = (struct stats_net_dev *) ((char *) a->buf[prev] + j * a->msize); } + if (DISPLAY_ZERO_OMIT(flags) && !memcmp(sndp, sndc, STATS_NET_DEV_SIZE2CMP)) + continue; + printf("%-11s", timestamp[curr]); if (!DISPLAY_HUMAN_READ(flags)) { @@ -1210,7 +1222,7 @@ __print_funct_t print_net_edev_stats(struct activity *a, int prev, int curr, memset(&snedzero, 0, STATS_NET_EDEV_SIZE); - if (dis) { + if (dis || DISPLAY_ZERO_OMIT(flags)) { print_hdr_line(timestamp[!curr], a, FIRST, DISPLAY_HUMAN_READ(flags) ? -1 : 0, 9); } @@ -1234,6 +1246,9 @@ __print_funct_t print_net_edev_stats(struct activity *a, int prev, int curr, snedp = (struct stats_net_edev *) ((char *) a->buf[prev] + j * a->msize); } + if (DISPLAY_ZERO_OMIT(flags) && !memcmp(snedp, snedc, STATS_NET_EDEV_SIZE2CMP)) + continue; + printf("%-11s", timestamp[curr]); if (!DISPLAY_HUMAN_READ(flags)) { @@ -2708,14 +2723,15 @@ __print_funct_t print_avg_pwr_usb_stats(struct activity *a, int prev, int curr, * * IN: * @a Activity structure with statistics. + * @prev Index in array where stats used as reference are. * @curr Index in array for current sample statistics. * @dispavg TRUE if displaying average statistics. *************************************************************************** */ -__print_funct_t stub_print_filesystem_stats(struct activity *a, int curr, int dispavg) +__print_funct_t stub_print_filesystem_stats(struct activity *a, int prev, int curr, int dispavg) { - int i, j; - struct stats_filesystem *sfc, *sfm; + int i, j, j0, found; + struct stats_filesystem *sfc, *sfp, *sfm; int unit = NO_UNIT; if (DISPLAY_UNIT(flags)) { @@ -2723,7 +2739,7 @@ __print_funct_t stub_print_filesystem_stats(struct activity *a, int curr, int di unit = UNIT_BYTE; } - if (dis) { + if (dis || DISPLAY_ZERO_OMIT(flags)) { print_hdr_line((dispavg ? _("Summary:") : timestamp[!curr]), a, FIRST + DISPLAY_MOUNT(a->opt_flags), -1, 9); } @@ -2731,25 +2747,56 @@ __print_funct_t stub_print_filesystem_stats(struct activity *a, int curr, int di for (i = 0; i < a->nr[curr]; i++) { sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize); - printf("%-11s", (dispavg ? _("Summary:") : timestamp[curr])); - cprintf_f(unit, 2, 9, 0, - unit < 0 ? (double) sfc->f_bfree / 1024 / 1024 : (double) sfc->f_bfree, - unit < 0 ? (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024 : - (double) (sfc->f_blocks - sfc->f_bfree)); - cprintf_pc(DISPLAY_UNIT(flags), 2, 9, 2, - /* f_blocks is not zero. But test it anyway ;-) */ - sfc->f_blocks ? SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) - : 0.0, - sfc->f_blocks ? SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) - : 0.0); - cprintf_u64(NO_UNIT, 2, 9, - (unsigned long long) sfc->f_ffree, - (unsigned long long) (sfc->f_files - sfc->f_ffree)); - cprintf_pc(DISPLAY_UNIT(flags), 1, 9, 2, - sfc->f_files ? SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) - : 0.0); - cprintf_in(IS_STR, " %s\n", - DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name, 0); + found = FALSE; + if (DISPLAY_ZERO_OMIT(flags) && !dispavg) { + + if (a->nr[prev] > 0) { + /* Look for corresponding fs in previous iteration */ + j = i; + + if (j >= a->nr[prev]) { + j = a->nr[prev] - 1; + } + + j0 = j; + + do { + sfp = (struct stats_filesystem *) ((char *) a->buf[prev] + j * a->msize); + if (!strcmp(sfp->fs_name, sfc->fs_name)) { + found = TRUE; + break; + } + if (++j >= a->nr[prev]) { + j = 0; + } + } + while (j != j0); + } + } + + if (!DISPLAY_ZERO_OMIT(flags) || dispavg || WANT_SINCE_BOOT(flags) || !found || + (found && memcmp(sfp, sfc, STATS_FILESYSTEM_SIZE2CMP))) { + + printf("%-11s", (dispavg ? _("Summary:") : timestamp[curr])); + cprintf_f(unit, 2, 9, 0, + unit < 0 ? (double) sfc->f_bfree / 1024 / 1024 : (double) sfc->f_bfree, + unit < 0 ? (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024 : + (double) (sfc->f_blocks - sfc->f_bfree)); + cprintf_pc(DISPLAY_UNIT(flags), 2, 9, 2, + /* f_blocks is not zero. But test it anyway ;-) */ + sfc->f_blocks ? SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) + : 0.0, + sfc->f_blocks ? SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) + : 0.0); + cprintf_u64(NO_UNIT, 2, 9, + (unsigned long long) sfc->f_ffree, + (unsigned long long) (sfc->f_files - sfc->f_ffree)); + cprintf_pc(DISPLAY_UNIT(flags), 1, 9, 2, + sfc->f_files ? SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) + : 0.0); + cprintf_in(IS_STR, " %s\n", + DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name, 0); + } if (!dispavg) { /* Save current filesystem in summary list */ @@ -2797,7 +2844,7 @@ __print_funct_t stub_print_filesystem_stats(struct activity *a, int curr, int di __print_funct_t print_filesystem_stats(struct activity *a, int prev, int curr, unsigned long long itv) { - stub_print_filesystem_stats(a, curr, FALSE); + stub_print_filesystem_stats(a, prev, curr, FALSE); } /* @@ -2814,7 +2861,7 @@ __print_funct_t print_filesystem_stats(struct activity *a, int prev, int curr, __print_funct_t print_avg_filesystem_stats(struct activity *a, int prev, int curr, unsigned long long itv) { - stub_print_filesystem_stats(a, 2, TRUE); + stub_print_filesystem_stats(a, prev, 2, TRUE); } /* @@ -2905,7 +2952,7 @@ __print_funct_t print_softnet_stats(struct activity *a, int prev, int curr, *ssnp = (struct stats_softnet *) a->buf[prev]; int i; - if (dis) { + if (dis || DISPLAY_ZERO_OMIT(flags)) { print_hdr_line(timestamp[!curr], a, FIRST, 7, 9); } @@ -2933,6 +2980,9 @@ __print_funct_t print_softnet_stats(struct activity *a, int prev, int curr, /* No */ continue; + if (DISPLAY_ZERO_OMIT(flags) && !memcmp(ssnp, ssnc,STATS_SOFTNET_SIZE)) + continue; + printf("%-11s", timestamp[curr]); if (!i) { diff --git a/rd_stats.h b/rd_stats.h index 9602780..909a46b 100644 --- a/rd_stats.h +++ b/rd_stats.h @@ -287,6 +287,7 @@ struct stats_net_dev { }; #define STATS_NET_DEV_SIZE (sizeof(struct stats_net_dev)) +#define STATS_NET_DEV_SIZE2CMP (STATS_NET_DEV_SIZE - MAX_IFACE_LEN - 1) #define STATS_NET_DEV_ULL 7 #define STATS_NET_DEV_UL 0 #define STATS_NET_DEV_U 1 @@ -306,6 +307,7 @@ struct stats_net_edev { }; #define STATS_NET_EDEV_SIZE (sizeof(struct stats_net_edev)) +#define STATS_NET_EDEV_SIZE2CMP (STATS_NET_EDEV_SIZE - MAX_IFACE_LEN) #define STATS_NET_EDEV_ULL 9 #define STATS_NET_EDEV_UL 0 #define STATS_NET_EDEV_U 0 @@ -657,10 +659,11 @@ struct stats_filesystem { char mountp[MAX_FS_LEN]; }; -#define STATS_FILESYSTEM_SIZE (sizeof(struct stats_filesystem)) -#define STATS_FILESYSTEM_ULL 5 -#define STATS_FILESYSTEM_UL 0 -#define STATS_FILESYSTEM_U 0 +#define STATS_FILESYSTEM_SIZE (sizeof(struct stats_filesystem)) +#define STATS_FILESYSTEM_SIZE2CMP (STATS_FILESYSTEM_SIZE - 2 * MAX_FS_LEN) +#define STATS_FILESYSTEM_ULL 5 +#define STATS_FILESYSTEM_UL 0 +#define STATS_FILESYSTEM_U 0 /* Structure for Fibre Channel HBA statistics */ struct stats_fchost { diff --git a/sa.h b/sa.h index ea43325..f08f8f8 100644 --- a/sa.h +++ b/sa.h @@ -98,6 +98,8 @@ #define S_F_LOCAL_TIME 0x00004000 #define S_F_PREFD_TIME_OUTPUT 0x00008000 #define S_F_SVG_SKIP 0x00010000 +/* Same value as S_F_SVG_SKIP above. Used for sar */ +#define S_F_ZERO_OMIT 0x00010000 /* Same value as S_F_SVG_SKIP above. Used for a different output format */ #define S_F_RAW_DEBUG_MODE 0x00010000 #define S_F_SVG_AUTOSCALE 0x00020000 @@ -126,6 +128,7 @@ #define PRINT_LOCAL_TIME(m) (((m) & S_F_LOCAL_TIME) == S_F_LOCAL_TIME) #define USE_PREFD_TIME_OUTPUT(m) (((m) & S_F_PREFD_TIME_OUTPUT) == S_F_PREFD_TIME_OUTPUT) #define SKIP_EMPTY_VIEWS(m) (((m) & S_F_SVG_SKIP) == S_F_SVG_SKIP) +#define DISPLAY_ZERO_OMIT(m) (((m) & S_F_ZERO_OMIT) == S_F_ZERO_OMIT) #define DISPLAY_DEBUG_MODE(m) (((m) & S_F_RAW_DEBUG_MODE) == S_F_RAW_DEBUG_MODE) #define AUTOSCALE_ON(m) (((m) & S_F_SVG_AUTOSCALE) == S_F_SVG_AUTOSCALE) #define DISPLAY_ONE_DAY(m) (((m) & S_F_SVG_ONE_DAY) == S_F_SVG_ONE_DAY) diff --git a/sar.c b/sar.c index 3c2a3d1..e6b8cc9 100644 --- a/sar.c +++ b/sar.c @@ -115,7 +115,7 @@ void usage(char *progname) fprintf(stderr, _("Options are:\n" "[ -A ] [ -B ] [ -b ] [ -C ] [ -D ] [ -d ] [ -F [ MOUNT ] ] [ -H ] [ -h ]\n" "[ -p ] [ -q ] [ -r [ ALL ] ] [ -S ] [ -t ] [ -u [ ALL ] ] [ -V ]\n" - "[ -v ] [ -W ] [ -w ] [ -y ] [ --help ] [ --human ] [ --sadc ]\n" + "[ -v ] [ -W ] [ -w ] [ -y ] [ -z ] [ --help ] [ --human ] [ --sadc ]\n" "[ -I { | SUM | ALL } ] [ -P { | ALL } ]\n" "[ -m { [,...] | ALL } ] [ -n { [,...] | ALL } ]\n" "[ -j { ID | LABEL | PATH | UUID | ... } ]\n" @@ -1387,6 +1387,11 @@ int main(int argc, char **argv) } } + else if (!strcmp(argv[opt], "-z")) { + flags |= S_F_ZERO_OMIT; + opt++; + } + else if ((strlen(argv[opt]) > 1) && (strlen(argv[opt]) < 4) && !strncmp(argv[opt], "-", 1) && -- 2.40.0