summaryrefslogtreecommitdiff
path: root/src/pmdas/jbd2
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/jbd2')
-rw-r--r--src/pmdas/jbd2/GNUmakefile73
-rwxr-xr-xsrc/pmdas/jbd2/Install31
-rwxr-xr-xsrc/pmdas/jbd2/Remove23
-rw-r--r--src/pmdas/jbd2/convert.h30
-rw-r--r--src/pmdas/jbd2/help115
-rw-r--r--src/pmdas/jbd2/pmda.c322
-rw-r--r--src/pmdas/jbd2/proc_jbd2.c148
-rw-r--r--src/pmdas/jbd2/proc_jbd2.h38
-rw-r--r--src/pmdas/jbd2/root6
-rw-r--r--src/pmdas/jbd2/root_jbd263
10 files changed, 849 insertions, 0 deletions
diff --git a/src/pmdas/jbd2/GNUmakefile b/src/pmdas/jbd2/GNUmakefile
new file mode 100644
index 0000000..ac19900
--- /dev/null
+++ b/src/pmdas/jbd2/GNUmakefile
@@ -0,0 +1,73 @@
+#
+# Copyright (c) 2013 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.
+#
+
+TOPDIR = ../../..
+include $(TOPDIR)/src/include/builddefs
+
+IAM = jbd2
+DOMAIN = JBD2
+CMDTARGET = pmdajbd2
+LIBTARGET = pmda_jbd2.so
+PMDAINIT = jbd2_init
+PMDADIR = $(PCP_PMDAS_DIR)/$(IAM)
+CONF_LINE = "jbd2 122 dso $(PMDAINIT) $(PMDADIR)/$(LIBTARGET)"
+
+CFILES = proc_jbd2.c pmda.c
+HFILES = proc_jbd2.h convert.h
+SCRIPTS = Install Remove
+VERSION_SCRIPT = exports
+HELPTARGETS = help.dir help.pag
+LSRCFILES = help root root_jbd2 $(SCRIPTS)
+LDIRT = $(HELPTARGETS) domain.h $(VERSION_SCRIPT)
+
+LLDLIBS = $(PCP_PMDALIB)
+LCFLAGS = $(INVISIBILITY)
+
+default: build-me
+
+include $(BUILDRULES)
+
+ifeq "$(TARGET_OS)" "linux"
+build-me: domain.h $(LIBTARGET) $(CMDTARGET) $(HELPTARGETS)
+ @if [ `grep -c $(CONF_LINE) ../pmcd.conf` -eq 0 ]; then \
+ echo $(CONF_LINE) >> ../pmcd.conf ; \
+ fi
+
+install: default
+ $(INSTALL) -m 755 -d $(PMDADIR)
+ $(INSTALL) -m 644 domain.h help $(HELPTARGETS) root root_jbd2 $(PMDADIR)
+ $(INSTALL) -m 755 $(LIBTARGET) $(CMDTARGET) $(SCRIPTS) $(PMDADIR)
+ $(INSTALL) -m 644 root_jbd2 $(PCP_VAR_DIR)/pmns/root_jbd2
+else
+build-me:
+install:
+endif
+
+default_pcp : default
+
+install_pcp : install
+
+$(HELPTARGETS) : help
+ $(RUN_IN_BUILD_ENV) $(TOPDIR)/src/newhelp/newhelp -n root_jbd2 -v 2 -o help < help
+
+$(VERSION_SCRIPT):
+ $(VERSION_SCRIPT_MAKERULE)
+
+domain.h: ../../pmns/stdpmid
+ $(DOMAIN_MAKERULE)
+
+pmda.o: domain.h
+pmda.o proc_jbd2.o: convert.h
+pmda.o proc_jbd2.o: proc_jbd2.h
+pmda.o: $(VERSION_SCRIPT)
diff --git a/src/pmdas/jbd2/Install b/src/pmdas/jbd2/Install
new file mode 100755
index 0000000..4b1daea
--- /dev/null
+++ b/src/pmdas/jbd2/Install
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Red Hat Inc.
+#
+# 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.
+#
+# Install the Linux JBD2 PMDA and/or PMNS
+#
+
+. $PCP_DIR/etc/pcp.env
+. $PCP_SHARE_DIR/lib/pmdaproc.sh
+
+iam=jbd2
+pmda_interface=4
+forced_restart=false
+daemon_opt=true
+pipe_opt=true
+dso_opt=true
+pmns_source=root_jbd2
+
+pmdaSetup
+pmdaInstall
+exit 0
diff --git a/src/pmdas/jbd2/Remove b/src/pmdas/jbd2/Remove
new file mode 100755
index 0000000..9e1158f
--- /dev/null
+++ b/src/pmdas/jbd2/Remove
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Red Hat Inc.
+#
+# 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.
+#
+# Remove the Linux JBD2 PMDA
+#
+
+. $PCP_DIR/etc/pcp.env
+. $PCP_SHARE_DIR/lib/pmdaproc.sh
+iam=jbd2
+pmdaSetup
+pmdaRemove
+exit 0
diff --git a/src/pmdas/jbd2/convert.h b/src/pmdas/jbd2/convert.h
new file mode 100644
index 0000000..69fc51a
--- /dev/null
+++ b/src/pmdas/jbd2/convert.h
@@ -0,0 +1,30 @@
+/*
+ * Size conversion for different sized types extracted from the
+ * kernel on different platforms, particularly where the sizeof
+ * "long" differs.
+ *
+ * Copyright (c) 2007-2008 Aconex. All Rights Reserved.
+ *
+ * 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.
+ */
+
+/*
+ * Some metrics are exported by the kernel as "unsigned long".
+ * On most 64bit platforms this is not the same size as an
+ * "unsigned int".
+ */
+#if defined(HAVE_64BIT_LONG)
+#define KERNEL_ULONG PM_TYPE_U64
+#define _pm_assign_ulong(atomp, val) do { (atomp)->ull = (val); } while (0)
+#else
+#define KERNEL_ULONG PM_TYPE_U32
+#define _pm_assign_ulong(atomp, val) do { (atomp)->ul = (val); } while (0)
+#endif
diff --git a/src/pmdas/jbd2/help b/src/pmdas/jbd2/help
new file mode 100644
index 0000000..9cfada7
--- /dev/null
+++ b/src/pmdas/jbd2/help
@@ -0,0 +1,115 @@
+#
+# Copyright (c) 2013 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.
+#
+# JBD2 PMDA help file in the ASCII format
+#
+# lines beginning with a # are ignored
+# lines beginning @ introduce a new entry of the form
+# @ metric_name oneline-text
+# help test goes
+# here over multiple lines
+# ...
+#
+# the metric_name is decoded against the default PMNS -- as a special case,
+# a name of the form NNN.MM (for numeric NNN and MM) is interpreted as an
+# instance domain identification, and the text describes the instance domain
+#
+# blank lines before the @ line are ignored
+#
+
+@ jbd2.njournals Count of active JBD2 (Journal Block Device v2) devices
+
+@ jbd2.transaction.count Total transactions committed per journal
+This metric is sourced from the per-device /proc/fs/jbd2 info file.
+
+@ jbd2.transaction.requested Total journal transactions requested per journal
+This metric is sourced from the per-device /proc/fs/jbd2 info file.
+
+@ jbd2.transaction.max_blocks Maximum transaction blocks (buffers) per journal
+This metric is sourced from the per-device /proc/fs/jbd2 info file.
+
+@ jbd2.transaction.average.time.waiting Average time waiting per journal
+Average time spent waiting for transactions to complete since mount.
+Exported directly from per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.average.time.request_delay Average request delay per journal
+Average request delay for all transactions to complete since mount.
+Exported directly from per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.average.time.running Average running time per journal
+Average transaction running time over all transactions since mount.
+Exported directly from per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.average.time.being_locked Average locked time per journal
+Average transaction locked time over all transactions since mount.
+Exported directly from per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.average.time.flushing_ordered_mode_data Average data flush time per journal
+Average time flushing data (ordered mode) for all transactions since
+mount. Exported directly from per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.average.time.logging Average logging time per journal
+Average time spent logging transactions for all transactions since
+mount. Exported directly from per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.average.time.committing Average commit time per journal
+Average time spent committing transactions for all transactions since
+mount. Exported directly from per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.average.blocks Average transaction blocks per journal
+Average number of blocks per transaction for all transactions.
+Exported directly from per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.average.blocks_logged Average logged blocks per journal
+Average number of blocks logged per transaction for all transactions.
+Exported directly from per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.average.handles Average handle count per journal
+Average number of handles used per transaction for all transactions.
+Exported directly from per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.total.time.waiting Total time waiting per journal
+Total time spent waiting for transactions to complete since mount.
+Derived from values in the per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.total.time.request_delay Total request delay per journal
+Total request delay for all transactions to complete since mount.
+Derived from values in the per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.total.time.running Total running time per journal
+Total transaction running time over all transactions since mount.
+Derived from values in the per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.total.time.being_locked Total locked time per journal
+Total transaction locked time over all transactions since mount.
+Derived from values in the per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.total.time.flushing_ordered_mode_data Total data flush time per journal
+Total time flushing data (ordered mode) for all transactions since
+mount. Derived from values in per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.total.time.logging Total logging time per journal
+Total time spent logging transactions for all transactions since
+mount. Derived from values in per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.total.blocks Total transaction blocks per journal
+Total number of blocks in all transactions since device mounted.
+Derived from values in the per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.total.blocks_logged Total logged blocks per journal
+Total number of blocks logged in all transactions since mount.
+Derived from values in the per-device /proc/fs/jbd2 info files.
+
+@ jbd2.transaction.total.handles Total handle count per journal
+Total count of handles used in all transactions since mount.
+Derived from values in the per-device /proc/fs/jbd2 info files.
diff --git a/src/pmdas/jbd2/pmda.c b/src/pmdas/jbd2/pmda.c
new file mode 100644
index 0000000..3c2dcba
--- /dev/null
+++ b/src/pmdas/jbd2/pmda.c
@@ -0,0 +1,322 @@
+/*
+ * Journal Block Device v2 PMDA
+ *
+ * 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 "domain.h"
+#include "convert.h"
+#include "proc_jbd2.h"
+
+static int _isDSO = 1; /* =0 I am a daemon */
+static char *prefix = "/proc/fs/jbd2";
+static char *username;
+
+#define JBD2_INDOM 0
+#define INDOM(i) (indomtab[i].it_indom)
+static pmdaIndom indomtab[] = {
+ { JBD2_INDOM, 0, NULL }, /* cached */
+};
+
+static pmdaMetric metrictab[] = {
+
+/* jbd2.njournals */
+ { NULL, { PMDA_PMID(0,0), PM_TYPE_U32, PM_INDOM_NULL,
+ PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
+
+/* jbd2.transaction.count */
+ { NULL, { PMDA_PMID(0,1), KERNEL_ULONG, JBD2_INDOM,
+ PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
+/* jbd2.transaction.requested */
+ { NULL, { PMDA_PMID(0,2), KERNEL_ULONG, JBD2_INDOM,
+ PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
+/* jbd2.transaction.max_blocks */
+ { NULL, { PMDA_PMID(0,3), PM_TYPE_U32, JBD2_INDOM,
+ PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, },
+
+/* jbd2.transaction.total.time.waiting */
+ { NULL, { PMDA_PMID(0,4), PM_TYPE_U64, JBD2_INDOM,
+ PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
+/* jbd2.transaction.total.time.request_delay */
+ { NULL, { PMDA_PMID(0,5), PM_TYPE_U64, JBD2_INDOM,
+ PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
+/* jbd2.transaction.total.time.running */
+ { NULL, { PMDA_PMID(0,6), PM_TYPE_U64, JBD2_INDOM,
+ PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
+/* jbd2.transaction.total.time.being_locked */
+ { NULL, { PMDA_PMID(0,7), PM_TYPE_U64, JBD2_INDOM,
+ PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
+/* jbd2.transaction.total.time.flushing_ordered_mode_data */
+ { NULL, { PMDA_PMID(0,8), PM_TYPE_U64, JBD2_INDOM,
+ PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
+/* jbd2.transaction.total.time.logging */
+ { NULL, { PMDA_PMID(0,9), PM_TYPE_U64, JBD2_INDOM,
+ PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
+/* jbd2.transaction.total.blocks */
+ { NULL, { PMDA_PMID(0,10), PM_TYPE_U64, JBD2_INDOM,
+ PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
+/* jbd2.transaction.total.blocks_logged */
+ { NULL, { PMDA_PMID(0,11), PM_TYPE_U64, JBD2_INDOM,
+ PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
+/* jbd2.transaction.total.handles */
+ { NULL, { PMDA_PMID(0,12), PM_TYPE_U64, JBD2_INDOM,
+ PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
+
+/* jbd2.transaction.average.time.waiting */
+ { NULL, { PMDA_PMID(0,13), PM_TYPE_U32, JBD2_INDOM,
+ PM_SEM_INSTANT, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
+/* jbd2.transaction.average.time.request_delay */
+ { NULL, { PMDA_PMID(0,14), PM_TYPE_U32, JBD2_INDOM,
+ PM_SEM_INSTANT, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
+/* jbd2.transaction.average.time.running */
+ { NULL, { PMDA_PMID(0,15), PM_TYPE_U32, JBD2_INDOM,
+ PM_SEM_INSTANT, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
+/* jbd2.transaction.average.time.being_locked */
+ { NULL, { PMDA_PMID(0,16), PM_TYPE_U32, JBD2_INDOM,
+ PM_SEM_INSTANT, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
+/* jbd2.transaction.average.time.flushing_ordered_mode_data */
+ { NULL, { PMDA_PMID(0,17), PM_TYPE_U32, JBD2_INDOM,
+ PM_SEM_INSTANT, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
+/* jbd2.transaction.average.time.logging */
+ { NULL, { PMDA_PMID(0,18), PM_TYPE_U32, JBD2_INDOM,
+ PM_SEM_INSTANT, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
+/* jbd2.transaction.average.time.committing */
+ { NULL, { PMDA_PMID(0,19), PM_TYPE_U64, JBD2_INDOM,
+ PM_SEM_INSTANT, PMDA_PMUNITS(0,1,0,0,PM_TIME_USEC,0) }, },
+/* jbd2.transaction.average.blocks */
+ { NULL, { PMDA_PMID(0,20), KERNEL_ULONG, JBD2_INDOM,
+ PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
+/* jbd2.transaction.average.blocks_logged */
+ { NULL, { PMDA_PMID(0,21), KERNEL_ULONG, JBD2_INDOM,
+ PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
+/* jbd2.transaction.average.handles */
+ { NULL, { PMDA_PMID(0,22), KERNEL_ULONG, JBD2_INDOM,
+ PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
+};
+
+static int
+jbd2_instance(pmInDom indom, int inst, char *name, __pmInResult **result, pmdaExt *pmda)
+{
+ refresh_jbd2(prefix, INDOM(JBD2_INDOM));
+ return pmdaInstance(indom, inst, name, result, pmda);
+}
+
+static int
+jbd2_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda)
+{
+ refresh_jbd2(prefix, INDOM(JBD2_INDOM));
+ return pmdaFetch(numpmid, pmidlist, resp, pmda);
+}
+
+static int
+jbd2_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom)
+{
+ __pmID_int *idp = (__pmID_int *)&(mdesc->m_desc.pmid);
+ int sts;
+ proc_jbd2_t *jbd2;
+
+ switch (idp->cluster) {
+ case 0:
+ if (!idp->item) { /* jbd2.njournals */
+ atom->ul = pmdaCacheOp(INDOM(JBD2_INDOM), PMDA_CACHE_SIZE_ACTIVE);
+ break;
+ }
+
+ /* lookup the instance (journal device) */
+ sts = pmdaCacheLookup(INDOM(JBD2_INDOM), inst, NULL, (void **)&jbd2);
+ if (sts < 0)
+ return sts;
+ if (sts != PMDA_CACHE_ACTIVE)
+ return PM_ERR_INST;
+ if (jbd2->version < 2)
+ return 0;
+
+ switch (idp->item) {
+
+ case 1: /* transaction.count */
+ _pm_assign_ulong(atom, jbd2->tid);
+ break;
+ case 2: /* transaction.requested */
+ if (jbd2->version < 3)
+ return 0;
+ _pm_assign_ulong(atom, jbd2->requested);
+ break;
+ case 3: /* transaction.max_blocks */
+ atom->ul = jbd2->max_buffers;
+ break;
+
+ case 4: /* transaction.total.time.waiting */
+ atom->ull = jbd2->waiting * jbd2->tid;
+ break;
+ case 5: /* transaction.total.time.request_delay */
+ if (jbd2->version < 3)
+ return 0;
+ atom->ull = jbd2->request_delay * jbd2->requested;
+ break;
+ case 6: /* transaction.total.time.running */
+ atom->ull = jbd2->running * jbd2->tid;
+ break;
+ case 7: /* transaction.total.time.being_locked */
+ atom->ull = jbd2->locked * jbd2->tid;
+ break;
+ case 8: /* transaction.total.time.flushing_ordered_mode_data */
+ atom->ull = jbd2->flushing * jbd2->tid;
+ break;
+ case 9: /* transaction.total.time.logging */
+ atom->ull = jbd2->logging * jbd2->tid;
+ break;
+ case 10: /* transaction.total.blocks */
+ atom->ull = jbd2->blocks * jbd2->tid;
+ break;
+ case 11: /* transaction.total.blocks_logged */
+ atom->ull = jbd2->blocks_logged * jbd2->tid;
+ break;
+ case 12: /* transaction.total.handles */
+ atom->ull = jbd2->handles * jbd2->tid;
+ break;
+
+ case 13: /* transaction.average.time.waiting */
+ atom->ul = jbd2->waiting;
+ break;
+ case 14: /* transaction.total.time.request_delay */
+ if (jbd2->version < 3)
+ return 0;
+ atom->ul = jbd2->request_delay;
+ break;
+ case 15: /* transaction.total.time.running */
+ atom->ul = jbd2->running;
+ break;
+ case 16: /* transaction.total.time.being_locked */
+ atom->ul = jbd2->locked;
+ break;
+ case 17: /* transaction.total.time.flushing_ordered_mode_data */
+ atom->ul = jbd2->flushing;
+ break;
+ case 18: /* transaction.total.time.logging */
+ atom->ul = jbd2->logging;
+ break;
+ case 19: /* transaction.average.time.committing */
+ atom->ull = jbd2->average_commit_time;
+ break;
+ case 20: /* transaction.total.blocks */
+ _pm_assign_ulong(atom, jbd2->blocks);
+ break;
+ case 21: /* transaction.total.blocks_logged */
+ _pm_assign_ulong(atom, jbd2->blocks_logged);
+ break;
+ case 22: /* transaction.total.handles */
+ _pm_assign_ulong(atom, jbd2->handles);
+ break;
+
+ default:
+ return PM_ERR_PMID;
+ }
+ break;
+
+ default: /* unknown cluster */
+ return PM_ERR_PMID;
+ }
+
+ return 1;
+}
+
+/*
+ * Initialise the agent (both daemon and DSO).
+ */
+void
+__PMDA_INIT_CALL
+jbd2_init(pmdaInterface *dp)
+{
+ size_t nmetrics, nindoms;
+
+ if (_isDSO) {
+ char helppath[MAXPATHLEN];
+ int sep = __pmPathSeparator();
+ snprintf(helppath, sizeof(helppath), "%s%c" "jbd2" "%c" "help",
+ pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
+ pmdaDSO(dp, PMDA_INTERFACE_4, "jbd2 DSO", helppath);
+ } else {
+ __pmSetProcessIdentity(username);
+ }
+
+ if (dp->status != 0)
+ return;
+
+ dp->version.four.instance = jbd2_instance;
+ dp->version.four.fetch = jbd2_fetch;
+ pmdaSetFetchCallBack(dp, jbd2_fetchCallBack);
+
+ nindoms = sizeof(indomtab)/sizeof(indomtab[0]);
+ nmetrics = sizeof(metrictab)/sizeof(metrictab[0]);
+
+ pmdaSetFlags(dp, PMDA_EXT_FLAG_DIRECT);
+ pmdaInit(dp, indomtab, nindoms, metrictab, nmetrics);
+}
+
+pmLongOptions longopts[] = {
+ PMDA_OPTIONS_HEADER("Options"),
+ PMOPT_DEBUG,
+ PMDAOPT_DOMAIN,
+ PMDAOPT_LOGFILE,
+ { "", 1, 'j', "PATH", "path to stats files (default \"/proc/fs/jbd2\")" },
+ PMDAOPT_USERNAME,
+ PMOPT_HELP,
+ PMDA_OPTIONS_END
+};
+
+pmdaOptions opts = {
+ .short_options = "D:d:l:j:U:?",
+ .long_options = longopts,
+};
+
+/*
+ * Set up the agent if running as a daemon.
+ */
+int
+main(int argc, char **argv)
+{
+ int c, sep = __pmPathSeparator();
+ pmdaInterface dispatch;
+ char help[MAXPATHLEN];
+
+ _isDSO = 0;
+ __pmSetProgname(argv[0]);
+ __pmGetUsername(&username);
+
+ snprintf(help, sizeof(help), "%s%c" "jbd2" "%c" "help",
+ pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
+ pmdaDaemon(&dispatch, PMDA_INTERFACE_4, pmProgname, JBD2, "jbd2.log", help);
+
+ while ((c = pmdaGetOptions(argc, argv, &opts, &dispatch)) != EOF) {
+ switch(c) {
+ case 'j':
+ prefix = opts.optarg;
+ break;
+ }
+ }
+ if (opts.errors) {
+ pmdaUsageMessage(&opts);
+ exit(1);
+ }
+ if (opts.username)
+ username = opts.username;
+
+ pmdaOpenLog(&dispatch);
+ jbd2_init(&dispatch);
+ pmdaConnect(&dispatch);
+ pmdaMain(&dispatch);
+ exit(0);
+}
diff --git a/src/pmdas/jbd2/proc_jbd2.c b/src/pmdas/jbd2/proc_jbd2.c
new file mode 100644
index 0000000..2a2692c
--- /dev/null
+++ b/src/pmdas/jbd2/proc_jbd2.c
@@ -0,0 +1,148 @@
+/*
+ * Linux JBD2 (ext3/ext4) driver metrics.
+ *
+ * Copyright (C) 2013 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 <ctype.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include "pmapi.h"
+#include "pmda.h"
+#include "proc_jbd2.h"
+
+enum {
+ HEADER_STATS,
+ SEEKING_STATS,
+ AVERAGE_STATS,
+};
+
+static int
+refresh_journal(const char *path, const char *dev, pmInDom indom)
+{
+ int n, state, indom_changed = 0;
+ char buf[MAXPATHLEN], *id;
+ unsigned long long value;
+ proc_jbd2_t *jp;
+ FILE *fp;
+
+ if (dev[0] == '.')
+ return 0; /* only interest is in device files */
+ if (snprintf(buf, sizeof(buf), "%s/%s/info", path, dev) == sizeof(buf))
+ return 0; /* ignore, dodgey command line args */
+ if ((fp = fopen(buf, "r")) == NULL)
+ return 0; /* no permission, ignore this entry */
+
+ if (pmdaCacheLookupName(indom, dev, &n, (void **)&jp) < 0 || !jp) {
+ if ((jp = (proc_jbd2_t *)calloc(1, sizeof(proc_jbd2_t))) != NULL)
+ indom_changed++;
+ }
+ if (!jp) {
+ fclose(fp);
+ return 0;
+ }
+
+ state = HEADER_STATS; /* seeking the header, initially */
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ switch (state) {
+ case HEADER_STATS:
+ if (sscanf(buf,
+ "%llu transactions (%llu requested), each up to %u blocks\n",
+ (unsigned long long *) &jp->tid,
+ (unsigned long long *) &jp->requested,
+ (unsigned int *) &jp->max_buffers) == 3) {
+ state = SEEKING_STATS;
+ jp->version = 3; /* 3.x kernel header format */
+ }
+ else if (sscanf(buf,
+ "%llu transaction, each up to %u blocks\n",
+ (unsigned long long *) &jp->tid,
+ (unsigned int *) &jp->max_buffers) == 2) {
+ state = SEEKING_STATS;
+ jp->version = 2; /* 2.x kernel header format */
+ }
+ break;
+
+ case SEEKING_STATS:
+ if (strncmp(buf, "average: \n", 8) == 0)
+ state = AVERAGE_STATS;
+ break;
+
+ case AVERAGE_STATS:
+ value = strtoull(buf, &id, 10);
+ if (id == buf)
+ continue;
+ else if (strcmp(id, "ms waiting for transaction\n") == 0)
+ jp->waiting = value;
+ else if (strcmp(id, "ms request delay\n") == 0)
+ jp->request_delay = value;
+ else if (strcmp(id, "ms running transaction\n") == 0)
+ jp->running = value;
+ else if (strcmp(id, "ms transaction was being locked\n") == 0)
+ jp->locked = value;
+ else if (strcmp(id, "ms flushing data (in ordered mode)\n") == 0)
+ jp->flushing = value;
+ else if (strcmp(id, "ms logging transaction\n") == 0)
+ jp->logging = value;
+ else if (strcmp(id, "us average transaction commit time\n") == 0)
+ jp->average_commit_time = value;
+ else if (strcmp(id, " handles per transaction\n") == 0)
+ jp->handles = value;
+ else if (strcmp(id, " blocks per transaction\n") == 0)
+ jp->blocks = value;
+ else if (strcmp(id, " logged blocks per transaction\n") == 0)
+ jp->blocks_logged = value;
+ break;
+
+ default:
+ break;
+ }
+ }
+ fclose(fp);
+
+ if (state != AVERAGE_STATS) {
+ if (indom_changed)
+ free(jp);
+ return 0;
+ }
+
+ pmdaCacheStore(indom, PMDA_CACHE_ADD, dev, jp);
+ return indom_changed;
+}
+
+int
+refresh_jbd2(const char *path, pmInDom jbd2_indom)
+{
+ DIR *dirp;
+ struct dirent *dent;
+ int indom_changes = 0;
+ static int first = 1;
+
+ if (first) {
+ /* initialize the instance domain caches */
+ pmdaCacheOp(jbd2_indom, PMDA_CACHE_LOAD);
+ indom_changes = 1;
+ first = 0;
+ }
+
+ pmdaCacheOp(jbd2_indom, PMDA_CACHE_INACTIVE);
+ if ((dirp = opendir(path)) == NULL)
+ return -ENOENT;
+ while ((dent = readdir(dirp)) != NULL)
+ indom_changes |= refresh_journal(path, dent->d_name, jbd2_indom);
+ closedir(dirp);
+
+ if (indom_changes)
+ pmdaCacheOp(jbd2_indom, PMDA_CACHE_SAVE);
+ return 0;
+}
diff --git a/src/pmdas/jbd2/proc_jbd2.h b/src/pmdas/jbd2/proc_jbd2.h
new file mode 100644
index 0000000..fb9c825
--- /dev/null
+++ b/src/pmdas/jbd2/proc_jbd2.h
@@ -0,0 +1,38 @@
+/*
+ * Linux JBD2 (ext3/ext4) driver metrics.
+ *
+ * Copyright (C) 2013 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.
+ */
+
+typedef struct {
+ __uint32_t version;
+ __uint32_t max_buffers;
+
+ __uint64_t tid;
+ __uint64_t requested;
+
+ __uint64_t waiting;
+ __uint64_t request_delay;
+ __uint64_t running;
+ __uint64_t locked;
+ __uint64_t flushing;
+ __uint64_t logging;
+ __uint64_t average_commit_time;
+
+ __uint64_t handles;
+
+ __uint64_t blocks;
+ __uint64_t blocks_logged;
+} proc_jbd2_t;
+
+extern int refresh_jbd2(const char *path, pmInDom jbd2_indom);
diff --git a/src/pmdas/jbd2/root b/src/pmdas/jbd2/root
new file mode 100644
index 0000000..12878cb
--- /dev/null
+++ b/src/pmdas/jbd2/root
@@ -0,0 +1,6 @@
+/*
+ * fake "root" for validating the local PMNS subtree
+ */
+
+#include <stdpmid>
+#include "root_jbd2"
diff --git a/src/pmdas/jbd2/root_jbd2 b/src/pmdas/jbd2/root_jbd2
new file mode 100644
index 0000000..7cb10cd
--- /dev/null
+++ b/src/pmdas/jbd2/root_jbd2
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+
+root {
+ jbd2
+}
+
+jbd2 {
+ njournals 122:0:0
+ transaction
+}
+
+jbd2.transaction {
+ count 122:0:1
+ requested 122:0:2
+ max_blocks 122:0:3
+ total
+ average
+}
+
+jbd2.transaction.total {
+ time
+ blocks 122:0:10
+ blocks_logged 122:0:11
+ handles 122:0:12
+}
+
+jbd2.transaction.total.time {
+ waiting 122:0:4
+ request_delay 122:0:5
+ running 122:0:6
+ being_locked 122:0:7
+ flushing_ordered_mode_data 122:0:8
+ logging 122:0:9
+}
+
+jbd2.transaction.average {
+ time
+ blocks 122:0:20
+ blocks_logged 122:0:21
+ handles 122:0:22
+}
+
+jbd2.transaction.average.time {
+ waiting 122:0:13
+ request_delay 122:0:14
+ running 122:0:15
+ being_locked 122:0:16
+ flushing_ordered_mode_data 122:0:17
+ logging 122:0:18
+ committing 122:0:19
+}