From 6053fe45ee2dd30adcf3bb6c142c003c4e92ed5a Mon Sep 17 00:00:00 2001 From: Sebastien GODARD Date: Fri, 28 Jan 2022 17:04:31 +0100 Subject: [PATCH] A_IRQ: Add new "--int=" option to sar and sadf The option "--int=" can be used with sar and sadf to enter a list of comma-separated interrupts values, ranges of interrupts values, or even interrupts names. These interrupts will then be displayed using option -I. Signed-off-by: Sebastien GODARD --- common.c | 82 ++++++++++++++++++++++++++++++++++++----------------- common.h | 3 ++ sa.h | 3 +- sa_common.c | 20 ++++++++++++- sadf.c | 14 ++++++--- sar.c | 15 +++++++--- 6 files changed, 101 insertions(+), 36 deletions(-) diff --git a/common.c b/common.c index 7097e17..a322db5 100644 --- a/common.c +++ b/common.c @@ -1553,6 +1553,59 @@ int parse_valstr(char *s, int max_val, int *val) return 0; } +/* + *************************************************************************** + * Parse string containing a single value or a range of values + * (e.g. "0,2-5,10-"). + * + * IN: + * @t String to parse. + * @max_val Upper limit that value should not reach. + * + * OUT: + * @val_low Low value in range + * @val High value in range. @val_low and @val are the same if it's + * a single value. + * + * RETURNS: + * 0 on success, 1 otherwise. + *************************************************************************** + */ +int parse_range_values(char *t, int max_val, int *val_low, int *val) +{ + char *s, *valstr, range[16]; + + /* Parse value or range of values */ + strncpy(range, t, 16); + range[15] = '\0'; + valstr = t; + + if ((s = strchr(range, '-')) != NULL) { + /* Possible range of values */ + *s = '\0'; + if (parse_valstr(range, max_val, val_low) || (*val_low < 0)) + return 1; + valstr = s + 1; + } + if (parse_valstr(valstr, max_val, val)) + return 1; + if (s && *val < 0) { + /* Range of values with no upper limit (e.g. "3-") */ + *val = max_val - 1; + } + if ((!s && (*val < 0)) || (s && (*val < *val_low))) + /* + * Individual value: string cannot be empty. + * Range of values: n-m: m can be empty (e.g. "3-") but + * cannot be lower than n. + */ + return 1; + if (!s) { + *val_low = *val; + } + return 0; +} + /* *************************************************************************** * Parse string containing a set of coma-separated values or ranges of @@ -1577,7 +1630,7 @@ int parse_valstr(char *s, int max_val, int *val) int parse_values(char *strargv, unsigned char bitmap[], int max_val, const char *__K_VALUE0) { int i, val_low, val; - char *t, *s, *valstr, range[16]; + char *t; if (!strcmp(strargv, K_ALL)) { /* Set bit for every possible values (CPU, IRQ, etc.) */ @@ -1595,32 +1648,9 @@ int parse_values(char *strargv, unsigned char bitmap[], int max_val, const char } else { /* Parse value or range of values */ - strncpy(range, t, 16); - range[15] = '\0'; - valstr = t; - if ((s = strchr(range, '-')) != NULL) { - /* Possible range of values */ - *s = '\0'; - if (parse_valstr(range, max_val, &val_low) || (val_low < 0)) - return 1; - valstr = s + 1; - } - if (parse_valstr(valstr, max_val, &val)) + if (parse_range_values(t, max_val, &val_low, &val)) return 1; - if (s && val < 0) { - /* Range of values with no upper limit (e.g. "3-") */ - val = max_val - 1; - } - if ((!s && (val < 0)) || (s && (val < val_low))) - /* - * Individual value: string cannot be empty. - * Range of values: n-m: m can be empty (e.g. "3-") but - * cannot be lower than n. - */ - return 1; - if (!s) { - val_low = val; - } + for (i = val_low; i <= val; i++) { bitmap[(i + 1) >> 3] |= 1 << ((i + 1) & 0x07); } diff --git a/common.h b/common.h index d25742d..0835ec7 100644 --- a/common.h +++ b/common.h @@ -113,6 +113,7 @@ #define C_ALWAYS "always" #define DIGITS "0123456789" +#define XDIGITS "0123456789-" /* *************************************************************************** @@ -297,6 +298,8 @@ double ll_sp_value (unsigned long long, unsigned long long, unsigned long long); int is_iso_time_fmt (void); +int parse_range_values + (char *t, int, int *, int *); int parse_values (char *, unsigned char[], int, const char *); int print_gal_header diff --git a/sa.h b/sa.h index b8a7075..dc5021f 100644 --- a/sa.h +++ b/sa.h @@ -299,6 +299,7 @@ #define NO_TM_START 0 #define NO_TM_END 0 #define NO_RESET 0 +#define NO_RANGE 0 #define NON_FATAL 0 #define FATAL 1 #define C_SAR 0 @@ -1537,7 +1538,7 @@ void init_custom_color_palette int next_slice (unsigned long long, unsigned long long, int, long); void parse_sa_devices - (char *, struct activity *, int, int *, int); + (char *, struct activity *, int, int *, int, int); int parse_sar_opt (char * [], int *, struct activity * [], uint64_t *, int); int parse_sa_P_opt diff --git a/sa_common.c b/sa_common.c index 529fbf5..b8d3dd6 100644 --- a/sa_common.c +++ b/sa_common.c @@ -2707,16 +2707,34 @@ int add_list_item(struct sa_item **list, char *item_name, int max_len) * @max_len Max length of a device name. * @opt Index in list of arguments. * @pos Position is string where is located the first device. + * @max_val If > 0 then ranges of values are allowed (e.g. 3-5,9-, etc.) + * Values are in range [0..@max_val]. * * OUT: * @opt Index on next argument. *************************************************************************** */ -void parse_sa_devices(char *argv, struct activity *a, int max_len, int *opt, int pos) +void parse_sa_devices(char *argv, struct activity *a, int max_len, int *opt, int pos, + int max_val) { + int i, val_low, val; char *t; + char svalue[9]; for (t = strtok(argv + pos, ","); t; t = strtok(NULL, ",")) { + + /* Test ranges of values, if allowed */ + if ((max_val > 0) && (strlen(t) <= 16) && (strspn(t, XDIGITS) == strlen(t))) { + if (parse_range_values(t, max_val, &val_low, &val) == 0) { + /* This is a real range of values: Save each if its values */ + for (i = val_low; i <= val; i++) { + snprintf(svalue, sizeof(svalue), "%d", i); + svalue[sizeof(svalue) - 1] = '\0'; + a->item_list_sz += add_list_item(&(a->item_list), svalue, max_len); + } + continue; + } + } a->item_list_sz += add_list_item(&(a->item_list), t, max_len); } if (a->item_list_sz) { diff --git a/sadf.c b/sadf.c index 0838f7d..da20a27 100644 --- a/sadf.c +++ b/sadf.c @@ -108,7 +108,7 @@ void usage(char *progname) fprintf(stderr, _("Options are:\n" "[ -C ] [ -c | -d | -g | -j | -l | -p | -r | -x ] [ -H ] [ -h ] [ -T | -t | -U ] [ -V ]\n" "[ -O [,...] ] [ -P { [,...] | ALL } ]\n" - "[ --dev= ] [ --fs= ] [ --iface= ]\n" + "[ --dev= ] [ --fs= ] [ --iface= ] [ --int= ]\n" "[ -s [ ] ] [ -e [ ] ]\n" "[ -- ]\n")); exit(1); @@ -1536,25 +1536,31 @@ int main(int argc, char **argv) else if (!strncmp(argv[opt], "--dev=", 6)) { /* Parse devices entered on the command line */ p = get_activity_position(act, A_DISK, EXIT_IF_NOT_FOUND); - parse_sa_devices(argv[opt], act[p], MAX_DEV_LEN, &opt, 6); + parse_sa_devices(argv[opt], act[p], MAX_DEV_LEN, &opt, 6, NO_RANGE); } else if (!strncmp(argv[opt], "--fs=", 5)) { /* Parse devices entered on the command line */ p = get_activity_position(act, A_FS, EXIT_IF_NOT_FOUND); - parse_sa_devices(argv[opt], act[p], MAX_FS_LEN, &opt, 5); + parse_sa_devices(argv[opt], act[p], MAX_FS_LEN, &opt, 5, NO_RANGE); } else if (!strncmp(argv[opt], "--iface=", 8)) { /* Parse devices entered on the command line */ p = get_activity_position(act, A_NET_DEV, EXIT_IF_NOT_FOUND); - parse_sa_devices(argv[opt], act[p], MAX_IFACE_LEN, &opt, 8); + parse_sa_devices(argv[opt], act[p], MAX_IFACE_LEN, &opt, 8, NO_RANGE); q = get_activity_position(act, A_NET_EDEV, EXIT_IF_NOT_FOUND); act[q]->item_list = act[p]->item_list; act[q]->item_list_sz = act[p]->item_list_sz; act[q]->options |= AO_LIST_ON_CMDLINE; } + else if (!strncmp(argv[opt], "--int=", 6)) { + /* Parse interrupts names entered on the command line */ + p = get_activity_position(act, A_IRQ, EXIT_IF_NOT_FOUND); + parse_sa_devices(argv[opt], act[p], MAX_SA_IRQ_LEN, &opt, 6, NR_IRQS); + } + else if (!strcmp(argv[opt], "-s")) { /* Get time start */ if (parse_timestamp(argv, &opt, &tm_start, DEF_TMSTART)) { diff --git a/sar.c b/sar.c index 99f1c7c..0be2423 100644 --- a/sar.c +++ b/sar.c @@ -126,7 +126,8 @@ void usage(char *progname) "[ -I { | SUM | ALL } ] [ -P { | ALL } ]\n" "[ -m { [,...] | ALL } ] [ -n { [,...] | ALL } ]\n" "[ -q [ [,...] | ALL ] ]\n" - "[ --dev= ] [ --fs= ] [ --iface= ]\n" + "[ --dev= ] [ --fs= ] [ --iface= ] " + "[ --int= ]\n" "[ --dec={ 0 | 1 | 2 } ] [ --help ] [ --human ] [ --pretty ] [ --sadc ]\n" "[ -j { SID | ID | LABEL | PATH | UUID | ... } ]\n" "[ -f [ ] | -o [ ] | -[0-9]+ ]\n" @@ -1315,25 +1316,31 @@ int main(int argc, char **argv) else if (!strncmp(argv[opt], "--dev=", 6)) { /* Parse devices entered on the command line */ p = get_activity_position(act, A_DISK, EXIT_IF_NOT_FOUND); - parse_sa_devices(argv[opt], act[p], MAX_DEV_LEN, &opt, 6); + parse_sa_devices(argv[opt], act[p], MAX_DEV_LEN, &opt, 6, NO_RANGE); } else if (!strncmp(argv[opt], "--fs=", 5)) { /* Parse devices entered on the command line */ p = get_activity_position(act, A_FS, EXIT_IF_NOT_FOUND); - parse_sa_devices(argv[opt], act[p], MAX_FS_LEN, &opt, 5); + parse_sa_devices(argv[opt], act[p], MAX_FS_LEN, &opt, 5, NO_RANGE); } else if (!strncmp(argv[opt], "--iface=", 8)) { /* Parse devices entered on the command line */ p = get_activity_position(act, A_NET_DEV, EXIT_IF_NOT_FOUND); - parse_sa_devices(argv[opt], act[p], MAX_IFACE_LEN, &opt, 8); + parse_sa_devices(argv[opt], act[p], MAX_IFACE_LEN, &opt, 8, NO_RANGE); q = get_activity_position(act, A_NET_EDEV, EXIT_IF_NOT_FOUND); act[q]->item_list = act[p]->item_list; act[q]->item_list_sz = act[p]->item_list_sz; act[q]->options |= AO_LIST_ON_CMDLINE; } + else if (!strncmp(argv[opt], "--int=", 6)) { + /* Parse interrupts names entered on the command line */ + p = get_activity_position(act, A_IRQ, EXIT_IF_NOT_FOUND); + parse_sa_devices(argv[opt], act[p], MAX_SA_IRQ_LEN, &opt, 6, NR_IRQS); + } + else if (!strcmp(argv[opt], "--help")) { /* Display help message */ display_help(argv[0]); -- 2.40.0