]> granicus.if.org Git - sysstat/commitdiff
sadc: Check that PSI statistics can be collected
authorSebastien GODARD <sysstat@users.noreply.github.com>
Sun, 19 Apr 2020 06:11:33 +0000 (08:11 +0200)
committerSebastien GODARD <sysstat@users.noreply.github.com>
Sun, 19 Apr 2020 06:11:33 +0000 (08:11 +0200)
Check that /proc/pressure directory exists for PSI statistics to be
collected.
Add all the necessary code that will be reusable to check if an activity
can be collected by sadc.

Signed-off-by: Sebastien GODARD <sysstat@users.noreply.github.com>
activity.c
common.c
common.h
rd_stats.h
sa.h
sa_common.c
sa_wrap.c
sadc.c

index 8f41ce6a4a3ca6305eb87ea4e8a339fe79e657c5..088ff30786b5f4e5bf303c5ad96c9341469ee2b5 100644 (file)
@@ -1876,11 +1876,11 @@ struct activity softnet_act = {
 /* Pressure-stall CPU activity */
 struct activity psi_cpu_act = {
        .id             = A_PSI_CPU,
-       .options        = AO_COLLECTED,
+       .options        = AO_COLLECTED + AO_DETECTED,
        .magic          = ACTIVITY_MAGIC_BASE,
        .group          = G_DEFAULT,
 #ifdef SOURCE_SADC
-       .f_count_index  = -1,
+       .f_count_index  = 11,
        .f_count2       = NULL,
        .f_read         = wrap_read_psicpu,
 #endif
@@ -1922,11 +1922,11 @@ struct activity psi_cpu_act = {
 /* Pressure-stall I/O activity */
 struct activity psi_io_act = {
        .id             = A_PSI_IO,
-       .options        = AO_COLLECTED,
+       .options        = AO_COLLECTED + AO_DETECTED,
        .magic          = ACTIVITY_MAGIC_BASE,
        .group          = G_DEFAULT,
 #ifdef SOURCE_SADC
-       .f_count_index  = -1,
+       .f_count_index  = 11,
        .f_count2       = NULL,
        .f_read         = wrap_read_psiio,
 #endif
@@ -1968,11 +1968,11 @@ struct activity psi_io_act = {
 /* Pressure-stall memory activity */
 struct activity psi_mem_act = {
        .id             = A_PSI_MEM,
-       .options        = AO_COLLECTED + AO_CLOSE_MARKUP,
+       .options        = AO_COLLECTED + AO_DETECTED + AO_CLOSE_MARKUP,
        .magic          = ACTIVITY_MAGIC_BASE,
        .group          = G_DEFAULT,
 #ifdef SOURCE_SADC
-       .f_count_index  = -1,
+       .f_count_index  = 11,
        .f_count2       = NULL,
        .f_read         = wrap_read_psimem,
 #endif
@@ -2026,7 +2026,8 @@ __nr_t (*f_count[NR_F_COUNT]) (struct activity *) = {
        wrap_get_in_nr,
        wrap_get_usb_nr,
        wrap_get_filesystem_nr,
-       wrap_get_fchost_nr
+       wrap_get_fchost_nr,
+       wrap_detect_psi
 };
 #endif
 
index ddfe75d8e79e4adc945859b88de096e3b13e61da..e8aef69cb67d908b65c2b4399dc6ae1561841807 100644 (file)
--- a/common.c
+++ b/common.c
@@ -410,6 +410,28 @@ int get_wwnid_from_pretty(char *pretty, unsigned long long *wwn, unsigned int *p
        return rc;
 }
 
+/*
+ ***************************************************************************
+ * Check if a directory exists.
+ *
+ * IN:
+ * @dirname    Name of the directory.
+ *
+ * RETURNS:
+ * TRUE if @dirname is actually an existing directory.
+ ***************************************************************************
+ */
+int check_dir(char *dirname)
+{
+       struct stat sb;
+
+       if (!stat(dirname, &sb) && S_ISDIR(sb.st_mode))
+               return 1;
+
+       return 0;
+}
+
+
 #ifndef SOURCE_SADC
 /*
  ***************************************************************************
index 86905ba6fc74c4bfd29c3b36c1bd5267510dbdd3..adbb7740566c805d74c37d6f6e0918a3f4b362b1 100644 (file)
--- a/common.h
+++ b/common.h
@@ -247,6 +247,8 @@ int extract_wwnid
        (char *, unsigned long long *, unsigned int *);
 int get_wwnid_from_pretty
        (char *, unsigned long long *, unsigned int *);
+int check_dir
+       (char *);
 
 #ifndef SOURCE_SADC
 int count_bits
index f89c3ef5c3806e2f10a1e6eb29f2741a5f6d6458..d982074343ba5a667f67c1e42eb149f516d4a123 100644 (file)
 #define NET_RPC_NFSD   PRE "/proc/net/rpc/nfsd"
 #define NET_SOFTNET    PRE "/proc/net/softnet_stat"
 #define LOADAVG                PRE "/proc/loadavg"
-#define PSI_CPU                PRE "/proc/pressure/cpu"
-#define PSI_IO         PRE "/proc/pressure/io"
-#define PSI_MEM                PRE "/proc/pressure/memory"
+#define PRESSURE       PRE "/proc/pressure"
+#define PSI_CPU                PRESSURE "/cpu"
+#define PSI_IO         PRESSURE "/io"
+#define PSI_MEM                PRESSURE "/memory"
 #define VMSTAT         PRE "/proc/vmstat"
 #define NET_SNMP       PRE "/proc/net/snmp"
 #define NET_SNMP6      PRE "/proc/net/snmp6"
diff --git a/sa.h b/sa.h
index b1abff45c2fbdd50d2418f3b650f8dbf572ca832..804e0c9bffc0747648914fad0edcbf231b155fec 100644 (file)
--- a/sa.h
+++ b/sa.h
@@ -25,7 +25,7 @@
 #define MAX_NR_ACT     256
 
 /* Number of functions used to count items */
-#define NR_F_COUNT     11
+#define NR_F_COUNT     12
 
 /* Activities */
 #define A_CPU          1
@@ -821,10 +821,22 @@ struct record_header {
  * be counted, even if the activity is not collected.
  */
 #define AO_ALWAYS_COUNTED      0x200
+/*
+ * Indicate that corresponding activity should be collected only
+ * if a test has been successfully passed before.
+ * The test corresponds to the count() function (see @f_count_index).
+ * This is intended for activities with a fixed number of items but
+ * whose {/proc|/sys} files are not necessarily available, e.g. depending
+ * on the kernel version used. Unlike activities with AO_COUNTED flag,
+ * those having AO_DETECTED flag won't have a @has_nr number preceding
+ * their statistics structures in datafile.
+ */
+#define AO_DETECTED            0x400
 
 #define IS_COLLECTED(m)                (((m) & AO_COLLECTED)        == AO_COLLECTED)
 #define IS_SELECTED(m)         (((m) & AO_SELECTED)         == AO_SELECTED)
 #define HAS_COUNT_FUNCTION(m)  (((m) & AO_COUNTED)          == AO_COUNTED)
+#define HAS_DETECT_FUNCTION(m) (((m) & AO_DETECTED)         == AO_DETECTED)
 #define HAS_PERSISTENT_VALUES(m) (((m) & AO_PERSISTENT)      == AO_PERSISTENT)
 #define CLOSE_MARKUP(m)                (((m) & AO_CLOSE_MARKUP)     == AO_CLOSE_MARKUP)
 #define HAS_MULTIPLE_OUTPUTS(m)        (((m) & AO_MULTIPLE_OUTPUTS) == AO_MULTIPLE_OUTPUTS)
@@ -876,7 +888,8 @@ struct activity {
        unsigned int group;
        /*
         * Index in f_count[] array to determine function used to count
-        * the number of items (serial lines, network interfaces, etc.) -> @nr
+        * the number of items (serial lines, network interfaces, etc.) for
+        * activities with AO_COUNTED flag. Determine @nr value.
         * Such a function should _always_ return a value greater than
         * or equal to 0.
         *
@@ -886,6 +899,10 @@ struct activity {
         * These functions are called even if corresponding activities have not
         * been selected, to make sure that all items have been calculated
         * (including #CPU, etc.)
+        *
+        * The count() function may also be used to know if an activity (with
+        * AO_DETECTED flag) can actually be collected based on the presence of
+        * {/proc|/sys} files.
         */
        int f_count_index;
        /*
@@ -1342,6 +1359,8 @@ __nr_t wrap_get_filesystem_nr
        (struct activity *);
 __nr_t wrap_get_fchost_nr
        (struct activity *);
+__nr_t wrap_detect_psi
+       (struct activity *);
 
 /* Functions used to read activities statistics */
 __read_funct_t wrap_read_stat_cpu
index c37fde1f85fae840b4f0b0bd38be256f5a70ba05..a38dfd6adb24568c7469f6e2d568fc0cb0d8057d 100644 (file)
@@ -276,17 +276,13 @@ int set_default_file(char *datafile, int d_off, int sa_name)
  */
 int check_alt_sa_dir(char *datafile, int d_off, int sa_name)
 {
-       struct stat sb;
-
-       if (stat(datafile, &sb) == 0) {
-               if (S_ISDIR(sb.st_mode)) {
-                       /*
-                        * This is a directory: So append
-                        * the default file name to it.
-                        */
-                       set_default_file(datafile, d_off, sa_name);
-                       return 1;
-               }
+       if (check_dir(datafile)) {
+               /*
+                * This is a directory: So append
+                * the default file name to it.
+                */
+               set_default_file(datafile, d_off, sa_name);
+               return 1;
        }
 
        return 0;
index df12b971b1114630ec974401e00852b041d84a75..5f0297019948d6f864888241784b35b75017cfaf 100644 (file)
--- a/sa_wrap.c
+++ b/sa_wrap.c
@@ -1509,3 +1509,19 @@ __nr_t wrap_get_fchost_nr(struct activity *a)
 
        return 0;
 }
+
+/*
+ ***************************************************************************
+ * Check that /proc/pressure directory exists.
+ *
+ * IN:
+ * @a  Activity structure.
+ *
+ * RETURNS:
+ * TRUE if directory exists.
+ ***************************************************************************
+ */
+__nr_t wrap_detect_psi(struct activity *a)
+{
+       return (check_dir(PRESSURE));
+}
diff --git a/sadc.c b/sadc.c
index 5516a81e52c7009e48b30b8d10838f1d2ee1ebd3..a020fbae80dea59330585ea3145cc33688e783a0 100644 (file)
--- a/sadc.c
+++ b/sadc.c
@@ -363,6 +363,19 @@ void sa_sys_init(void)
                        act[i]->options &= ~AO_COLLECTED;
                }
 
+               if (HAS_DETECT_FUNCTION(act[i]->options) && IS_COLLECTED(act[i]->options)) {
+                       idx = act[i]->f_count_index;
+
+                       /* Detect if files needed by activity exist */
+                       if (f_count_results[idx] < 0) {
+                               f_count_results[idx] = (f_count[idx])(act[i]);
+                       }
+                       if (f_count_results[idx] == 0) {
+                               /* Files not present */
+                               act[i]->options &= ~AO_COLLECTED;
+                       }
+               }
+
                /* Set default activity list */
                id_seq[i] = act[i]->id;
        }
@@ -674,7 +687,7 @@ void write_stats(int ofd)
                        continue;
 
                if (IS_COLLECTED(act[p]->options)) {
-                       if (act[p]->f_count_index >= 0) {
+                       if (HAS_COUNT_FUNCTION(act[p]->options) && (act[p]->f_count_index >= 0)) {
                                if (write_all(ofd, &(act[p]->_nr0), sizeof(__nr_t)) != sizeof(__nr_t)) {
                                        p_write_error();
                                }
@@ -937,7 +950,7 @@ void open_ofile(int *ofd, char ofile[], int restart_mark)
                }
 
                if ((file_act[i].has_nr && (act[p]->f_count_index < 0)) ||
-                   (!file_act[i].has_nr && (act[p]->f_count_index >= 0))) {
+                   (!file_act[i].has_nr && (act[p]->f_count_index >= 0) && HAS_COUNT_FUNCTION(act[p]->options))) {
 #ifdef DEBUG
                        fprintf(stderr, "%s: %s: has_nr=%d count_index=%d\n",
                                __FUNCTION__, act[p]->name, file_act[i].has_nr, act[p]->f_count_index);