Re: [PATCH 3/3] lsirq,irqtop: add support for reading data from given file

Joe Jin <[email protected]>
Newsgroups org.kernel.vger.util-linux
Message-ID <[email protected]>
On 2/27/25 17:41, zhenwei pi wrote:
> Does the '--input IRQFILE' change?
>
> irqtop reads 'IRQFILE' and uses the current one to calculate the increment from the previous one, I'm curious about this case ...
>
> But I guess lsirq would work fine.
Make sense, I'll remove this option from irqtop.

Thanks,
Joe

>
> On 2/27/25 12:49, Joe Jin wrote:
>> This is helpful for analyzng data saved from other system.
>>
>> Signed-off-by: Joe Jin <[email protected]>
>> Cc: Zhenwei Pi <[email protected]>
>> Cc: Sami Kerola <[email protected]>
>> ---
>>   bash-completion/irqtop  |  4 ++++
>>   bash-completion/lsirq   |  4 ++++
>>   sys-utils/irq-common.c  | 19 +++++++++----------
>>   sys-utils/irq-common.h  |  3 ++-
>>   sys-utils/irqtop.1.adoc |  3 +++
>>   sys-utils/irqtop.c      | 28 +++++++++++++++++++++++++---
>>   sys-utils/lsirq.1.adoc  |  3 +++
>>   sys-utils/lsirq.c       | 28 ++++++++++++++++++++++++----
>>   8 files changed, 74 insertions(+), 18 deletions(-)
>>
>> diff --git a/bash-completion/irqtop b/bash-completion/irqtop
>> index 47b7b0af6..3bea5fc0e 100644
>> --- a/bash-completion/irqtop
>> +++ b/bash-completion/irqtop
>> @@ -15,6 +15,9 @@ _irqtop_module()
>>           '-C'|'--cpu-list')
>>               return 0
>>               ;;
>> +        '-i'|'--input')
>> +            COMPREPLY=( $(compgen -W "input file" -- $cur) )
>> +            ;;
>>           '-t'|'--threshold')
>>               return 0
>>               ;;
>> @@ -51,6 +54,7 @@ _irqtop_module()
>>           --cpu-stat
>>           --cpu-list
>>           --delay
>> +        --input
>>           --number
>>           --sort
>>           --output
>> diff --git a/bash-completion/lsirq b/bash-completion/lsirq
>> index 4c3c9f04f..b913eecd0 100644
>> --- a/bash-completion/lsirq
>> +++ b/bash-completion/lsirq
>> @@ -5,6 +5,9 @@ _lsirq_module()
>>       cur="${COMP_WORDS[COMP_CWORD]}"
>>       prev="${COMP_WORDS[COMP_CWORD-1]}"
>>       case $prev in
>> +        '-i'|'--input')
>> +            COMPREPLY=( $(compgen -W "input file" -- $cur) )
>> +            ;;
>>           '-o'|'--output')
>>               local prefix realcur OUTPUT
>>               realcur="${cur##*,}"
>> @@ -35,6 +38,7 @@ _lsirq_module()
>>       OPTS="    --json
>>           --pairs
>>           --noheadings
>> +        --input
>>           --output
>>           --softirq
>>           --sort
>> diff --git a/sys-utils/irq-common.c b/sys-utils/irq-common.c
>> index f069d8a63..560dd4b82 100644
>> --- a/sys-utils/irq-common.c
>> +++ b/sys-utils/irq-common.c
>> @@ -233,7 +233,8 @@ static bool cpu_in_list(int cpu, size_t setsize, cpu_set_t *cpuset)
>>   /*
>>    * irqinfo - parse the system's interrupts
>>    */
>> -static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpuset)
>> +static struct irq_stat *get_irqinfo(const char *input_file, int softirq,
>> +                    size_t setsize, cpu_set_t *cpuset)
>>   {
>>       FILE *irqfile;
>>       char *line = NULL, *tmp;
>> @@ -247,18 +248,15 @@ static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpus
>>       stat->irq_info = xmalloc(sizeof(*stat->irq_info) * IRQ_INFO_LEN);
>>       stat->nr_irq_info = IRQ_INFO_LEN;
>>   -    if (softirq)
>> -        irqfile = fopen(_PATH_PROC_SOFTIRQS, "r");
>> -    else
>> -        irqfile = fopen(_PATH_PROC_INTERRUPTS, "r");
>> +    irqfile = fopen(input_file, "r");
>>       if (!irqfile) {
>> -        warn(_("cannot open %s"), _PATH_PROC_INTERRUPTS);
>> +        warn(_("cannot open %s"), input_file);
>>           goto free_stat;
>>       }
>>         /* read header firstly */
>>       if (getline(&line, &len, irqfile) < 0) {
>> -        warn(_("cannot read %s"), _PATH_PROC_INTERRUPTS);
>> +        warn(_("cannot read %s"), input_file);
>>           goto close_file;
>>       }
>>   @@ -270,7 +268,7 @@ static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpus
>>         stat->cpus =  xcalloc(stat->nr_active_cpu, sizeof(struct irq_cpu));
>>   -    /* parse each line of _PATH_PROC_INTERRUPTS */
>> +    /* parse each line of input file */
>>       while (getline(&line, &len, irqfile) >= 0) {
>>           unsigned long count;
>>           size_t index;
>> @@ -527,7 +525,8 @@ struct libscols_table *get_scols_cpus_table(struct irq_output *out,
>>       return NULL;
>>   }
>>   -struct libscols_table *get_scols_table(struct irq_output *out,
>> +struct libscols_table *get_scols_table(const char *input_file,
>> +                          struct irq_output *out,
>>                             struct irq_stat *prev,
>>                             struct irq_stat **xstat,
>>                             int softirq,
>> @@ -542,7 +541,7 @@ struct libscols_table *get_scols_table(struct irq_output *out,
>>       size_t i;
>>         /* the stats */
>> -    stat = get_irqinfo(softirq, setsize, cpuset);
>> +    stat = get_irqinfo(input_file, softirq, setsize, cpuset);
>>       if (!stat)
>>           return NULL;
>>   diff --git a/sys-utils/irq-common.h b/sys-utils/irq-common.h
>> index 02b72d752..b9cf72d2a 100644
>> --- a/sys-utils/irq-common.h
>> +++ b/sys-utils/irq-common.h
>> @@ -73,7 +73,8 @@ void irq_print_columns(FILE *f, int nodelta);
>>   void set_sort_func_by_name(struct irq_output *out, const char *name);
>>   void set_sort_func_by_key(struct irq_output *out, const char c);
>>   -struct libscols_table *get_scols_table(struct irq_output *out,
>> +struct libscols_table *get_scols_table(const char *input_file,
>> +                                              struct irq_output *out,
>>                                                 struct irq_stat *prev,
>>                                                 struct irq_stat **xstat,
>>                                                 int softirq,
>> diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
>> index 75cfe2e41..715008d07 100644
>> --- a/sys-utils/irqtop.1.adoc
>> +++ b/sys-utils/irqtop.1.adoc
>> @@ -37,6 +37,9 @@ Specify cpus in list format to show.
>>   *-d*, *--delay* _seconds_::
>>   Update interrupt output every _seconds_ intervals.
>>   +*-i*, *--input* _file_::
>> +Read data from _file_ (Which was created by other tools, e.g. sosreport).
>> +
>>   *-n*, *--number* _number_::
>>   Specifies the maximum _number_ of iterations before quitting.
>>   diff --git a/sys-utils/irqtop.c b/sys-utils/irqtop.c
>> index ba5680671..4cf1dc79a 100644
>> --- a/sys-utils/irqtop.c
>> +++ b/sys-utils/irqtop.c
>> @@ -87,6 +87,8 @@ struct irqtop_ctl {
>>       bool    batch;
>>       bool    request_exit,
>>           softirq;
>> +
>> +    char    *input;
>>   };
>>     #define irqtop_batch_mode(ctl) ((ctl)->batch == true)
>> @@ -122,8 +124,9 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
>>       char timestr[64], *data, *data0, *p;
>>         /* make irqs table */
>> -    table = get_scols_table(out, ctl->prev_stat, &stat, ctl->softirq,
>> -                ctl->threshold, ctl->setsize, ctl->cpuset);
>> +    table = get_scols_table(ctl->input, out, ctl->prev_stat, &stat,
>> +                ctl->softirq, ctl->threshold, ctl->setsize,
>> +                ctl->cpuset);
>>       if (!table) {
>>           ctl->request_exit = 1;
>>           return 1;
>> @@ -292,6 +295,7 @@ static void __attribute__((__noreturn__)) usage(void)
>>       fputs(_(" -c, --cpu-stat <mode> show per-cpu stat (auto, enable, disable)\n"), stdout);
>>       fputs(_(" -C, --cpu-list <list> specify cpus in list format\n"), stdout);
>>       fputs(_(" -d, --delay <secs>   delay updates\n"), stdout);
>> +    fputs(_(" -i, --input <file>   read data from file\n"), stdout);
>>       fputs(_(" -n, --number <number> the maximum number of iterations\n"), stdout);
>>       fputs(_(" -o, --output <list>  define which output columns to use\n"), stdout);
>>       fputs(_(" -s, --sort <column>  specify sort column\n"), stdout);
>> @@ -325,6 +329,7 @@ static void parse_args(    struct irqtop_ctl *ctl,
>>           {"cpu-stat", required_argument, NULL, 'c'},
>>           {"cpu-list", required_argument, NULL, 'C'},
>>           {"delay", required_argument, NULL, 'd'},
>> +        {"input", required_argument, NULL, 'i'},
>>           {"number", required_argument, NULL, 'n'},
>>           {"sort", required_argument, NULL, 's'},
>>           {"output", required_argument, NULL, 'o'},
>> @@ -336,7 +341,7 @@ static void parse_args(    struct irqtop_ctl *ctl,
>>       };
>>       int o;
>>   -    while ((o = getopt_long(argc, argv, "bc:C:d:n:o:s:St:hV", longopts, NULL)) != -1) {
>> +    while ((o = getopt_long(argc, argv, "bc:C:d:i:n:o:s:St:hV", longopts, NULL)) != -1) {
>>           switch (o) {
>>           case 'b':
>>               ctl->batch = true;
>> @@ -376,6 +381,13 @@ static void parse_args(    struct irqtop_ctl *ctl,
>>                   ctl->timer.it_value = ctl->timer.it_interval;
>>               }
>>               break;
>> +        case 'i':
>> +            ctl->input = strdup(optarg);
>> +            if (!ctl->input)
>> +                err_oom();
>> +            ctl->number = 1;
>> +            ctl->batch = true;
>> +            break;
>>           case 'n':
>>               ctl->number = str2num_or_err(optarg, 10,
>>                       _("failed to parse number argument"),
>> @@ -402,6 +414,15 @@ static void parse_args(    struct irqtop_ctl *ctl,
>>           }
>>       }
>>   +    if (ctl->input == NULL) {
>> +        if (ctl->softirq == 1)
>> +            ctl->input = strdup(_PATH_PROC_SOFTIRQS);
>> +        else
>> +            ctl->input = strdup(_PATH_PROC_INTERRUPTS);
>> +        if (!ctl->input)
>> +            err_oom();
>> +    }
>> +
>>       /* default */
>>       if (!out->ncolumns) {
>>           out->columns[out->ncolumns++] = COL_IRQ;
>> @@ -453,6 +474,7 @@ int main(int argc, char **argv)
>>         free_irqstat(ctl.prev_stat);
>>       free(ctl.hostname);
>> +    free(ctl.input);
>>       cpuset_free(ctl.cpuset);
>>         if (ctl.batch == false) {
>> diff --git a/sys-utils/lsirq.1.adoc b/sys-utils/lsirq.1.adoc
>> index 02aea16b3..dd265710c 100644
>> --- a/sys-utils/lsirq.1.adoc
>> +++ b/sys-utils/lsirq.1.adoc
>> @@ -25,6 +25,9 @@ The default output is subject to change. So whenever possible, you should avoid
>>   *-n*, *--noheadings*::
>>   Don't print headings.
>>   +*-i*, *--input* _file_::
>> +Read data from _file_ (Which was created by other tools, e.g. sosreport).
>> +
>>   *-o*, *--output* _list_::
>>   Specify which output columns to print. Use *--help* to get a list of all supported columns. The default list of columns may be extended if list is specified in the format _+list_.
>>   diff --git a/sys-utils/lsirq.c b/sys-utils/lsirq.c
>> index e31addaf5..45d542919 100644
>> --- a/sys-utils/lsirq.c
>> +++ b/sys-utils/lsirq.c
>> @@ -29,16 +29,17 @@
>>   #include "optutils.h"
>>   #include "strutils.h"
>>   #include "xalloc.h"
>> +#include "pathnames.h"
>>     #include "irq-common.h"
>>   -static int print_irq_data(struct irq_output *out,
>> +static int print_irq_data(const char *input_file, struct irq_output *out,
>>                 int softirq, unsigned long threshold,
>>                 size_t setsize, cpu_set_t *cpuset)
>>   {
>>       struct libscols_table *table;
>>   -    table = get_scols_table(out, NULL, NULL, softirq, threshold, setsize, cpuset);
>> +    table = get_scols_table(input_file, out, NULL, NULL, softirq, threshold, setsize, cpuset);
>>       if (!table)
>>           return -1;
>>   @@ -58,6 +59,7 @@ static void __attribute__((__noreturn__)) usage(void)
>>       fputs(USAGE_OPTIONS, stdout);
>>       fputs(_(" -J, --json           use JSON output format\n"), stdout);
>>       fputs(_(" -P, --pairs          use key=\"value\" output format\n"), stdout);
>> +    fputs(_(" -i, --input          read data from input file\n"), stdout);
>>       fputs(_(" -n, --noheadings     don't print headings\n"), stdout);
>>       fputs(_(" -o, --output <list>  define which output columns to use\n"), stdout);
>>       fputs(_(" -s, --sort <column>  specify sort column\n"), stdout);
>> @@ -82,6 +84,7 @@ int main(int argc, char **argv)
>>       static const struct option longopts[] = {
>>           {"sort", required_argument, NULL, 's'},
>>           {"noheadings", no_argument, NULL, 'n'},
>> +        {"input", required_argument, NULL, 'i'},
>>           {"output", required_argument, NULL, 'o'},
>>           {"threshold", required_argument, NULL, 't'},
>>           {"cpu-list", required_argument, NULL, 'C'},
>> @@ -103,10 +106,11 @@ int main(int argc, char **argv)
>>       cpu_set_t *cpuset = NULL;
>>       size_t setsize = 0;
>>       int softirq = 0;
>> +    char *input = NULL;
>>         setlocale(LC_ALL, "");
>>   -    while ((c = getopt_long(argc, argv, "no:s:t:C:ShJPV", longopts, NULL)) != -1) {
>> +    while ((c = getopt_long(argc, argv, "i:no:s:t:C:ShJPV", longopts, NULL)) != -1) {
>>           err_exclusive_options(c, longopts, excl, excl_st);
>>             switch (c) {
>> @@ -116,6 +120,11 @@ int main(int argc, char **argv)
>>           case 'P':
>>               out.pairs = 1;
>>               break;
>> +        case 'i':
>> +            input = strdup(optarg);
>> +            if (!input)
>> +                err_oom();
>> +            break;
>>           case 'n':
>>               out.no_headings = 1;
>>               break;
>> @@ -157,6 +166,15 @@ int main(int argc, char **argv)
>>           }
>>       }
>>   +    if (input == NULL) {
>> +        if (softirq == 1)
>> +            input = strdup(_PATH_PROC_SOFTIRQS);
>> +        else
>> +            input = strdup(_PATH_PROC_INTERRUPTS);
>> +        if (!input)
>> +            err_oom();
>> +    }
>> +
>>       /* default */
>>       if (!out.ncolumns) {
>>           out.columns[out.ncolumns++] = COL_IRQ;
>> @@ -171,8 +189,10 @@ int main(int argc, char **argv)
>>                   irq_column_name_to_id) < 0)
>>           exit(EXIT_FAILURE);
>>   -    if (print_irq_data(&out, softirq, threshold, setsize, cpuset) < 0)
>> +    if (print_irq_data(input, &out, softirq, threshold, setsize, cpuset) < 0)
>>           return EXIT_FAILURE;
>>   +    free(input);
>> +
>>       return EXIT_SUCCESS;
>>   }
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.