]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
irqtop: support -C/--cpu-list
authorzhenwei pi <pizhenwei@bytedance.com>
Tue, 29 Mar 2022 08:59:51 +0000 (16:59 +0800)
committerKarel Zak <kzak@redhat.com>
Fri, 1 Apr 2022 08:21:31 +0000 (10:21 +0200)
Specify cpus list format to show by -C/--cpu-list parameters, for
example, on an AMD server with 192 CPUs, to show statistics on NUMA
node 1:
  ~# ./irqtop -d 1 -C 48-95,144-191

Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
bash-completion/irqtop
sys-utils/irq-common.c
sys-utils/irq-common.h
sys-utils/irqtop.1.adoc
sys-utils/irqtop.c
sys-utils/lsirq.c

index a3812acbb63deb5bb8f5914abe8683f479677f07..7688f673c4ba1bd7e2a33d23c043fa759e2bda19 100644 (file)
@@ -9,6 +9,9 @@ _irqtop_module()
                        COMPREPLY=( $(compgen -W "auto enable disable" -- $cur) )
                        return 0
                        ;;
+               '-C'|'--cpu-list')
+                       return 0
+                       ;;
                '-d'|'--delay')
                        COMPREPLY=( $(compgen -W "secs" -- $cur) )
                        return 0
@@ -35,6 +38,7 @@ _irqtop_module()
                        ;;
        esac
        OPTS="  --cpu-stat
+               --cpu-list
                --delay
                --sort
                --output
index aa10f7e05bd7d253d1e1948ba255903140fc6539..1bdcfad3168aa62d4d7ec71c11cadfb8e600d812 100644 (file)
@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <locale.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -228,10 +229,19 @@ static char *remove_repeated_spaces(char *str)
        return str;
 }
 
+static bool cpu_in_list(int cpu, size_t setsize, cpu_set_t *cpuset)
+{
+       /* no -C/--cpu-list specified, use all the CPUs */
+       if (!cpuset)
+               return true;
+
+       return CPU_ISSET_S(cpu, setsize, cpuset);
+}
+
 /*
  * irqinfo - parse the system's interrupts
  */
-static struct irq_stat *get_irqinfo(int softirq)
+static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpuset)
 {
        FILE *irqfile;
        char *line = NULL, *tmp;
@@ -292,9 +302,11 @@ static struct irq_stat *get_irqinfo(int softirq)
 
                        if (sscanf(tmp, " %10lu", &count) != 1)
                                continue;
-                       curr->total += count;
-                       cpu->total += count;
-                       stat->total_irq += count;
+                       if (cpu_in_list(index, setsize, cpuset)) {
+                               curr->total += count;
+                               cpu->total += count;
+                               stat->total_irq += count;
+                       }
 
                        tmp += 11;
                }
@@ -422,13 +434,15 @@ void set_sort_func_by_key(struct irq_output *out, char c)
 
 struct libscols_table *get_scols_cpus_table(struct irq_output *out,
                                        struct irq_stat *prev,
-                                       struct irq_stat *curr)
+                                       struct irq_stat *curr,
+                                       size_t setsize,
+                                       cpu_set_t *cpuset)
 {
        struct libscols_table *table;
        struct libscols_column *cl;
        struct libscols_line *ln;
        char colname[sizeof(stringify_value(LONG_MAX))];
-       size_t i;
+       size_t i, j;
 
        if (prev) {
                for (i = 0; i < curr->nr_active_cpu; i++) {
@@ -454,6 +468,8 @@ struct libscols_table *get_scols_cpus_table(struct irq_output *out,
                scols_table_new_column(table, "", 0, SCOLS_FL_RIGHT);
 
        for (i = 0; i < curr->nr_active_cpu; i++) {
+               if (!cpu_in_list(i, setsize, cpuset))
+                       continue;
                snprintf(colname, sizeof(colname), "cpu%zu", i);
                cl = scols_table_new_column(table, colname, 0, SCOLS_FL_RIGHT);
                if (cl == NULL) {
@@ -469,12 +485,14 @@ struct libscols_table *get_scols_cpus_table(struct irq_output *out,
        if (!ln || (!out->json && scols_line_set_data(ln, 0, "%irq:") != 0))
                goto err;
 
-       for (i = 0; i < curr->nr_active_cpu; i++) {
+       for (i = 0, j = 0; i < curr->nr_active_cpu; i++) {
                struct irq_cpu *cpu = &curr->cpus[i];
                char *str;
 
+               if (!cpu_in_list(i, setsize, cpuset))
+                       continue;
                xasprintf(&str, "%0.1f", (double)((long double) cpu->total / (long double) curr->total_irq * 100.0));
-               if (str && scols_line_refer_data(ln, i + 1, str) != 0)
+               if (str && scols_line_refer_data(ln, ++j, str) != 0)
                        goto err;
        }
 
@@ -484,14 +502,16 @@ struct libscols_table *get_scols_cpus_table(struct irq_output *out,
        if (!ln || (!out->json && scols_line_set_data(ln, 0, _("%delta:")) != 0))
                goto err;
 
-       for (i = 0; i < curr->nr_active_cpu; i++) {
+       for (i = 0, j = 0; i < curr->nr_active_cpu; i++) {
                struct irq_cpu *cpu = &curr->cpus[i];
                char *str;
 
+               if (!cpu_in_list(i, setsize, cpuset))
+                       continue;
                if (!curr->delta_irq)
                        continue;
                xasprintf(&str, "%0.1f", (double)((long double) cpu->delta / (long double) curr->delta_irq * 100.0));
-               if (str && scols_line_refer_data(ln, i + 1, str) != 0)
+               if (str && scols_line_refer_data(ln, ++j, str) != 0)
                        goto err;
        }
 
@@ -504,7 +524,9 @@ struct libscols_table *get_scols_cpus_table(struct irq_output *out,
 struct libscols_table *get_scols_table(struct irq_output *out,
                                              struct irq_stat *prev,
                                              struct irq_stat **xstat,
-                                             int softirq)
+                                             int softirq,
+                                             size_t setsize,
+                                             cpu_set_t *cpuset)
 {
        struct libscols_table *table;
        struct irq_info *result;
@@ -513,7 +535,7 @@ struct libscols_table *get_scols_table(struct irq_output *out,
        size_t i;
 
        /* the stats */
-       stat = get_irqinfo(softirq);
+       stat = get_irqinfo(softirq, setsize, cpuset);
        if (!stat)
                return NULL;
 
index c4f1fa3a25b62433a93bc5aa287806ac141f1100..04c43207eea1ea1397a63bb38a96e5f0b5f4d935 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "c.h"
 #include "nls.h"
+#include "cpuset.h"
 
 /* supported columns */
 enum {
@@ -63,10 +64,14 @@ void set_sort_func_by_key(struct irq_output *out, const char c);
 struct libscols_table *get_scols_table(struct irq_output *out,
                                               struct irq_stat *prev,
                                               struct irq_stat **xstat,
-                                              int softirq);
+                                              int softirq,
+                                              size_t setsize,
+                                              cpu_set_t *cpuset);
 
 struct libscols_table *get_scols_cpus_table(struct irq_output *out,
                                         struct irq_stat *prev,
-                                        struct irq_stat *curr);
+                                        struct irq_stat *curr,
+                                        size_t setsize,
+                                        cpu_set_t *cpuset);
 
 #endif /* UTIL_LINUX_H_IRQ_COMMON */
index 3f215d2f0e66c27056abe957bb82e7d698ddc515..a310ded9d5ca5f064a14776d5f4bf536a30fffc9 100644 (file)
@@ -28,6 +28,9 @@ Specify which output columns to print. Use *--help* to get a list of all support
 *-c*, *--cpu-stat* _mode_::
 Show per-cpu statistics by specified mode. Available modes are: *auto*, *enable*, *disable*. The default option *auto* detects the width of window, then shows the per-cpu statistics if the width of window is large enouth to show a full line of statistics.
 
+*-C*, *--cpu-list* _list_::
+Specify cpus in list format to show.
+
 *-d*, *--delay* _seconds_::
 Update interrupt output every _seconds_ intervals.
 
index adf75591b1e9905d703a37a88e2578c0bfd1eb97..eb0e6bc661b5e6ed5704587c8a80699076ee0aa8 100644 (file)
@@ -57,6 +57,7 @@
 #include <libsmartcols.h>
 
 #include "closestream.h"
+#include "cpuset.h"
 #include "monotonic.h"
 #include "pathnames.h"
 #include "strutils.h"
@@ -83,6 +84,8 @@ struct irqtop_ctl {
 
        struct itimerspec timer;
        struct irq_stat *prev_stat;
+       size_t setsize;
+       cpu_set_t *cpuset;
 
        enum irqtop_cpustat_mode cpustat_mode;
        unsigned int request_exit:1;
@@ -111,7 +114,8 @@ 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);
+       table = get_scols_table(out, ctl->prev_stat, &stat, ctl->softirq, ctl->setsize,
+                               ctl->cpuset);
        if (!table) {
                ctl->request_exit = 1;
                return 1;
@@ -122,7 +126,8 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
 
        /* make cpus table */
        if (ctl->cpustat_mode != IRQTOP_CPUSTAT_DISABLE) {
-               cpus = get_scols_cpus_table(out, ctl->prev_stat, stat);
+               cpus = get_scols_cpus_table(out, ctl->prev_stat, stat, ctl->setsize,
+                                           ctl->cpuset);
                scols_table_reduce_termwidth(cpus, 1);
                if (ctl->cpustat_mode == IRQTOP_CPUSTAT_AUTO)
                        scols_table_enable_nowrap(cpus, 1);
@@ -261,6 +266,7 @@ static void __attribute__((__noreturn__)) usage(void)
 
        fputs(USAGE_OPTIONS, stdout);
        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(_(" -o, --output <list>  define which output columns to use\n"), stdout);
        fputs(_(" -s, --sort <column>  specify sort column\n"), stdout);
@@ -290,6 +296,7 @@ static void parse_args(     struct irqtop_ctl *ctl,
        const char *outarg = NULL;
        static const struct option longopts[] = {
                {"cpu-stat", required_argument, NULL, 'c'},
+               {"cpu-list", required_argument, NULL, 'C'},
                {"delay", required_argument, NULL, 'd'},
                {"sort", required_argument, NULL, 's'},
                {"output", required_argument, NULL, 'o'},
@@ -300,7 +307,7 @@ static void parse_args(     struct irqtop_ctl *ctl,
        };
        int o;
 
-       while ((o = getopt_long(argc, argv, "c:d:o:s:ShV", longopts, NULL)) != -1) {
+       while ((o = getopt_long(argc, argv, "c:C:d:o:s:ShV", longopts, NULL)) != -1) {
                switch (o) {
                case 'c':
                        if (!strcmp(optarg, "auto"))
@@ -312,6 +319,21 @@ static void parse_args(    struct irqtop_ctl *ctl,
                        else
                                errx(EXIT_FAILURE, _("unsupported mode '%s'"), optarg);
                        break;
+               case 'C':
+                       {
+                               int ncpus = get_max_number_of_cpus();
+                               if (ncpus <= 0)
+                                       errx(EXIT_FAILURE, _("cannot determine NR_CPUS; aborting"));
+
+                               ctl->cpuset = cpuset_alloc(ncpus, &ctl->setsize, NULL);
+                               if (!ctl->cpuset)
+                                       err(EXIT_FAILURE, _("cpuset_alloc failed"));
+
+                               if (cpulist_parse(optarg, ctl->cpuset, ctl->setsize, 0))
+                                       errx(EXIT_FAILURE, _("failed to parse CPU list: %s"),
+                                               optarg);
+                       }
+                       break;
                case 'd':
                        {
                                struct timeval delay;
@@ -388,6 +410,7 @@ int main(int argc, char **argv)
 
        free_irqstat(ctl.prev_stat);
        free(ctl.hostname);
+       cpuset_free(ctl.cpuset);
 
        if (is_tty)
                tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_tty);
index 1a90efe21740c5e8c8421f6f510887cef0d3df8c..375476dca84ab686878396200ddcdc42f1f491b8 100644 (file)
@@ -42,7 +42,7 @@ static int print_irq_data(struct irq_output *out, int softirq)
 {
        struct libscols_table *table;
 
-       table = get_scols_table(out, NULL, NULL, softirq);
+       table = get_scols_table(out, NULL, NULL, softirq, 0, NULL);
        if (!table)
                return -1;