/* 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
/* 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
/* 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
wrap_get_in_nr,
wrap_get_usb_nr,
wrap_get_filesystem_nr,
- wrap_get_fchost_nr
+ wrap_get_fchost_nr,
+ wrap_detect_psi
};
#endif
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
/*
***************************************************************************
(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
#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"
#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
* 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)
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.
*
* 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;
/*
(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
*/
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;
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));
+}
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;
}
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();
}
}
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);