]> granicus.if.org Git - sysstat/commitdiff
mpstat : add -H option to handle vCPU physical hotplug
authorShaleen Bathla <shaleen.bathla@oracle.com>
Tue, 4 Oct 2022 07:09:02 +0000 (12:39 +0530)
committerShaleen Bathla <shaleen.bathla@oracle.com>
Wed, 5 Oct 2022 07:03:17 +0000 (12:33 +0530)
For virtualized environments, physical CPU hotplug can occur.
OR to be more precise vCPU physical hotplug can occur.

Currently, mpstat does not detect physical hotplug when running with an interval.
Example : mpstat -P ALL 5
When -H option is given, display stats of physically hotplugged vCPU also.
Example : mpstat -H -P ALL 5

This is done only when -H option is provided to remain legacy compatible.

Also updated the man page describing the new option.

Signed-off-by: Shaleen Bathla <shaleen.bathla@oracle.com>
man/mpstat.1
mpstat.c
mpstat.h

index 08e45a5a19b9ce70ad003ce5219a06621c64b273..31ad48733b2562557bad20d97f011e7fdc3c93e1 100644 (file)
@@ -4,7 +4,7 @@
 mpstat \- Report processors related statistics.
 
 .SH SYNOPSIS
-.B mpstat [ -A ] [ --dec={ 0 | 1 | 2 } ] [ -n ] [ -u ] [ -T ] [ -V ] [ -I {
+.B mpstat [ -A ] [ --dec={ 0 | 1 | 2 } ] [ -n ] [ -u ] [ -T ] [ -V ] [ -H ] [ -I {
 .IB "keyword" "[,...] | ALL } ] [ -N { " "node_list " "| ALL } ] [ -o JSON ] [ -P {"
 .IB "cpu_list " "| ALL } ] [ " "interval " "[ " "count " "] ]"
 
@@ -44,6 +44,8 @@ unless these options are explicitly set on the command line.
 .B --dec={ 0 | 1 | 2 }
 Specify the number of decimal places to use (0 to 2, default value is 2).
 .TP
+.B -H
+Detect and Display stats of physically hotplugged vCPUs also
 .BI "-I { " "keyword" "[,...] | ALL }"
 Report interrupts statistics.
 .RI "Possible " "keywords " "are"
index 859d3049378f7dbe748d9a22b74fb207a1910d19..8f7957d3dc0aa9baa2ce2001bf9bc8984cb0e8c9 100644 (file)
--- a/mpstat.c
+++ b/mpstat.c
@@ -1,6 +1,7 @@
 /*
  * mpstat: per-processor statistics
  * (C) 2000-2022 by Sebastien GODARD (sysstat <at> orange.fr)
+ * Copyright (c) 2022, Oracle and/or its affiliates.
  *
  ***************************************************************************
  * This program is free software; you can redistribute it and/or modify it *
@@ -134,7 +135,7 @@ void usage(char *progname)
                progname);
 
        fprintf(stderr, _("Options are:\n"
-                         "[ -A ] [ -n ] [ -T ] [ -u ] [ -V ]\n"
+                         "[ -A ] [ -n ] [ -T ] [ -u ] [ -V ] [ -H ]\n"
                          "[ -I { SUM | CPU | SCPU | ALL } ] [ -N { <node_list> | ALL } ]\n"
                          "[ --dec={ 0 | 1 | 2 } ] [ -o JSON ] [ -P { <cpu_list> | ALL } ]\n"));
        exit(1);
@@ -1957,13 +1958,18 @@ void read_interrupts_stat(char *file, struct stats_irqcpu *st_ic[], int ic_nr, i
  * IN:
  * @dis_hdr    Set to TRUE if the header line must always be printed.
  * @rows       Number of rows of screen.
+ *
+ * OUT:
+ * @new_cpu_nr Return 0 as default.
+ *             Return new_cpu_nr (!=0) if physical vCPU hotplug occured.
  ***************************************************************************
  */
-void rw_mpstat_loop(int dis_hdr, int rows)
+int rw_mpstat_loop(int dis_hdr, int rows)
 {
        struct stats_cpu *scc;
        int i;
        int curr = 1, dis = 1;
+       int new_cpu_nr = 0;
        unsigned long lines = rows;
 
        /* Read system uptime and CPU stats */
@@ -2063,7 +2069,7 @@ void rw_mpstat_loop(int dis_hdr, int rows)
 
        if (sigint_caught)
                /* SIGINT signal caught during first interval: Exit immediately */
-               return;
+               return 0;
 
        do {
                /*
@@ -2131,6 +2137,14 @@ void rw_mpstat_loop(int dis_hdr, int rows)
                                curr ^= 1;
                        }
                }
+
+               /* -H option is given and vCPU physical hotplug occured */
+               if (USE_OPTION_H(flags)) {
+                       new_cpu_nr = get_cpu_nr(~0, TRUE);
+                       if (new_cpu_nr > cpu_nr) {
+                               return new_cpu_nr;
+                       }
+               }
        }
        while (count);
 
@@ -2141,6 +2155,52 @@ void rw_mpstat_loop(int dis_hdr, int rows)
        else {
                write_stats_avg(curr, dis_hdr);
        }
+       return 0;
+}
+
+/*
+ ***************************************************************************
+ * Detect physical vCPU hotplug and call rw_mpstat_loop to display stats
+ *
+ * IN:
+ * @dis_hdr    Set to TRUE if the header line must always be printed.
+ * @rows       Number of rows of screen.
+ ***************************************************************************
+ */
+void mpstat_loop(int dis_hdr, int rows)
+{
+       int new_cpu_nr = 0;
+
+       while (1) {
+               /* Main loop for reading-writing stats */
+               new_cpu_nr = rw_mpstat_loop(dis_hdr, rows);
+
+               /* Handle vCPU physical hotplug */
+               if (new_cpu_nr == 0) {
+                       return;
+               }
+               else {
+                       /* Update the highest processor number */
+                       cpu_nr = new_cpu_nr;
+
+                       /* Recalculate number of interrupts per processor */
+                       irqcpu_nr = get_irqcpu_nr(INTERRUPTS, NR_IRQS, cpu_nr) +
+                                       NR_IRQCPU_PREALLOC;
+                       /* Recalculate number of soft interrupts per processor */
+                       softirqcpu_nr = get_irqcpu_nr(SOFTIRQS, NR_IRQS, cpu_nr) +
+                                       NR_IRQCPU_PREALLOC;
+
+                       /*
+                        * Reallocate cpu stats structs :
+                        * global, proc0, proc1, ..., proc$(prev_cpu_nr-1).
+                        * global, proc0, proc1, ..., proc$(prev_cpu_nr-1), ..., proc$(cpu_nr-1).
+                        */
+                       salloc_mp_struct(cpu_nr + 1, FALSE);
+
+                       /* Get NUMA node placement */
+                       node_nr = get_node_placement(cpu_nr, cpu_per_node, cpu2node);
+               }
+       }
 }
 
 /*
@@ -2299,6 +2359,11 @@ int main(int argc, char **argv)
                                        print_version();
                                        break;
 
+                               case 'H':
+                                       /* Display physically hotplugged vCPU also */
+                                       flags |= F_OPTION_H;
+                                       break;
+
                                default:
                                        usage(argv[0]);
                                }
@@ -2401,7 +2466,7 @@ int main(int argc, char **argv)
                         DISPLAY_JSON_OUTPUT(flags));
 
        /* Main loop */
-       rw_mpstat_loop(dis_hdr, rows);
+       mpstat_loop(dis_hdr, rows);
 
        /* Free structures */
        sfree_mp_struct();
index 4a10a3e9465e326ee58ef049a8cb48f5d4d09b10..4d8685ab68787d420846251f0264d8abcabfcc23 100644 (file)
--- a/mpstat.h
+++ b/mpstat.h
 #define F_OPTION_N     0x08
 /* Display topology */
 #define F_TOPOLOGY     0x10
+/* Indicate that option -H has been used */
+#define F_OPTION_H     0x20
 
 #define USE_OPTION_P(m)                (((m) & F_OPTION_P) == F_OPTION_P)
 #define USE_OPTION_A(m)                (((m) & F_OPTION_A) == F_OPTION_A)
 #define DISPLAY_JSON_OUTPUT(m) (((m) & F_JSON_OUTPUT) == F_JSON_OUTPUT)
 #define USE_OPTION_N(m)                (((m) & F_OPTION_N) == F_OPTION_N)
 #define DISPLAY_TOPOLOGY(m)    (((m) & F_TOPOLOGY) == F_TOPOLOGY)
+#define USE_OPTION_H(m)                (((m) & F_OPTION_H) == F_OPTION_H)
 
 #define K_SUM  "SUM"
 #define K_CPU  "CPU"