diff options
Diffstat (limited to 'src/pmdas/jbd2')
-rw-r--r-- | src/pmdas/jbd2/GNUmakefile | 73 | ||||
-rwxr-xr-x | src/pmdas/jbd2/Install | 31 | ||||
-rwxr-xr-x | src/pmdas/jbd2/Remove | 23 | ||||
-rw-r--r-- | src/pmdas/jbd2/convert.h | 30 | ||||
-rw-r--r-- | src/pmdas/jbd2/help | 115 | ||||
-rw-r--r-- | src/pmdas/jbd2/pmda.c | 322 | ||||
-rw-r--r-- | src/pmdas/jbd2/proc_jbd2.c | 148 | ||||
-rw-r--r-- | src/pmdas/jbd2/proc_jbd2.h | 38 | ||||
-rw-r--r-- | src/pmdas/jbd2/root | 6 | ||||
-rw-r--r-- | src/pmdas/jbd2/root_jbd2 | 63 |
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 +} |