summaryrefslogtreecommitdiff
path: root/src/pmdas/gfs2/control.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/gfs2/control.c')
-rw-r--r--src/pmdas/gfs2/control.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/pmdas/gfs2/control.c b/src/pmdas/gfs2/control.c
new file mode 100644
index 0000000..20d5c6f
--- /dev/null
+++ b/src/pmdas/gfs2/control.c
@@ -0,0 +1,123 @@
+/*
+ * GFS2 trace-point metrics control.
+ *
+ * Copyright (c) 2013 - 2014 Red Hat.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pmapi.h"
+#include "impl.h"
+#include "pmda.h"
+#include "control.h"
+#include "ftrace.h"
+#include "worst_glock.h"
+#include "latency.h"
+
+/* Locations of the enable files for the gfs2 tracepoints */
+const char *control_locations[] = {
+ [CONTROL_ALL] = "/sys/kernel/debug/tracing/events/gfs2/enable",
+ [CONTROL_GLOCK_STATE_CHANGE] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_glock_state_change/enable",
+ [CONTROL_GLOCK_PUT] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_glock_put/enable",
+ [CONTROL_DEMOTE_RQ] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_demote_rq/enable",
+ [CONTROL_PROMOTE] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_promote/enable",
+ [CONTROL_GLOCK_QUEUE] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_glock_queue/enable",
+ [CONTROL_GLOCK_LOCK_TIME] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_glock_lock_time/enable",
+ [CONTROL_PIN] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_pin/enable",
+ [CONTROL_LOG_FLUSH] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_log_flush/enable",
+ [CONTROL_LOG_BLOCKS] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_log_blocks/enable",
+ [CONTROL_AIL_FLUSH] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_ail_flush/enable",
+ [CONTROL_BLOCK_ALLOC] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_block_alloc/enable",
+ [CONTROL_BMAP] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_bmap/enable",
+ [CONTROL_RS] = "/sys/kernel/debug/tracing/events/gfs2/gfs2_rs/enable",
+ [CONTROL_BUFFER_SIZE_KB] = "/sys/kernel/debug/tracing/buffer_size_kb",
+ [CONTROL_GLOBAL_TRACING] = "/sys/kernel/debug/tracing/tracing_on"
+};
+
+/*
+ * Refresh callback for the control metrics; For traceppoints that have file
+ * based enabling we use gfs2_control_check_value(), for other metrics we
+ * call their corresponding "get" value.
+ */
+int
+gfs2_control_fetch(int item, pmAtomValue *atom)
+{
+ if (item >= CONTROL_ALL && item <= CONTROL_GLOBAL_TRACING) {
+ atom->ul = gfs2_control_check_value(control_locations[item]);
+
+ } else if (item == CONTROL_WORSTGLOCK) {
+ atom->ul = worst_glock_get_state();
+
+ } else if (item == CONTROL_LATENCY) {
+ atom->ul = latency_get_state();
+
+ } else if (item == CONTROL_FTRACE_GLOCK_THRESHOLD) {
+ atom->ul = ftrace_get_threshold();
+
+ } else {
+ return PM_ERR_PMID;
+
+ }
+ return 1;
+}
+
+/*
+ * Attempt open the enable file for the given filename and set the value
+ * contained in pmValueSet. The enable file for the tracepoint only accept
+ * 0 for disabled or 1 for enabled.
+ */
+int
+gfs2_control_set_value(const char *filename, pmValueSet *vsp)
+{
+ FILE *fp;
+ int sts = 0;
+ int value = vsp->vlist[0].value.lval;
+
+ if (strncmp(filename, control_locations[CONTROL_BUFFER_SIZE_KB],
+ sizeof(control_locations[CONTROL_BUFFER_SIZE_KB])-1) == 0) {
+ /* Special case for buffer_size_kb */
+ if (value < 0 || value > 131072) /* Allow upto 128mb buffer per CPU */
+ return - oserror();
+
+ } else if (value < 0 || value > 1) {
+ return -oserror();
+ }
+
+ fp = fopen(filename, "w");
+ if (!fp) {
+ sts = -oserror(); /* EACCESS, File not found (stats not supported) */;
+ } else {
+ fprintf(fp, "%d\n", value);
+ fclose(fp);
+ }
+ return sts;
+}
+
+/*
+ * We check the tracepoint enable file given by filename and return the value
+ * contained. This should either be 0 for disabled or 1 for enabled. In the
+ * event of permissions or file not found we will return zero.
+ */
+int
+gfs2_control_check_value(const char *filename)
+{
+ FILE *fp;
+ char buffer[16];
+ int value = 0;
+
+ fp = fopen(filename, "r");
+ if (fp) {
+ while (fgets(buffer, sizeof(buffer), fp) != NULL)
+ sscanf(buffer, "%d", &value);
+ fclose(fp);
+ }
+ return value;
+}