diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2014-10-26 12:33:50 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2014-10-26 12:33:50 +0400 |
commit | 47e6e7c84f008a53061e661f31ae96629bc694ef (patch) | |
tree | 648a07f3b5b9d67ce19b0fd72e8caa1175c98f1a /src/pmdas/solaris/zpool.c | |
download | pcp-debian/3.9.10.tar.gz |
Debian 3.9.10debian/3.9.10debian
Diffstat (limited to 'src/pmdas/solaris/zpool.c')
-rw-r--r-- | src/pmdas/solaris/zpool.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/pmdas/solaris/zpool.c b/src/pmdas/solaris/zpool.c new file mode 100644 index 0000000..2f402f2 --- /dev/null +++ b/src/pmdas/solaris/zpool.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2009 Max Matveev. 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. + */ + +#include <libzfs.h> + +#include "common.h" + +struct zpool_stats { + int vdev_stats_fresh; + vdev_stat_t vds; +}; + +static libzfs_handle_t *zh; +static int zp_added; + +/* + * For each zpool check the name in the instance cache, if it's not there then + * add it to the cache. Regardless if it's the first time we've seen this one + * or if it was in the cache before refresh the stats + */ +static int +zp_cache_pool(zpool_handle_t *zp, void *arg) +{ + nvlist_t *cfg = zpool_get_config(zp, NULL); + char *zpname = (char *)zpool_get_name(zp); + struct zpool_stats *zps = NULL; + pmInDom zpindom = indomtab[ZPOOL_INDOM].it_indom; + uint_t cnt = 0; + vdev_stat_t *vds; + int rv; + int inst; + nvlist_t *vdt; + + if ((rv = pmdaCacheLookupName(zpindom, zpname, &inst, + (void **)&zps)) != PMDA_CACHE_ACTIVE) { + int newpool = (zps == NULL); + + if (rv != PMDA_CACHE_INACTIVE || zps == NULL) { + zps = malloc(sizeof(*zps)); + if (zps == NULL) { + __pmNotifyErr(LOG_WARNING, + "Cannot allocate memory to hold stats for " + "zpool '%s'\n", + zpname); + goto done; + } + } + + rv = pmdaCacheStore(zpindom, PMDA_CACHE_ADD, zpname, zps); + if (rv < 0) { + __pmNotifyErr(LOG_WARNING, + "Cannot add '%s' to the cache " + "for instance domain %s: %s\n", + zpname, pmInDomStr(zpindom), pmErrStr(rv)); + free(zps); + goto done; + } + zp_added += newpool; + } + + rv = nvlist_lookup_nvlist(cfg, ZPOOL_CONFIG_VDEV_TREE, &vdt); + if (rv != 0) { + __pmNotifyErr(LOG_ERR, "Cannot get vdev tree for '%s': %d %d\n", + zpname, rv, oserror()); + zps->vdev_stats_fresh = 0; + } else { + /* accommodate zpool api changes ... */ +#ifdef ZPOOL_CONFIG_VDEV_STATS + rv = nvlist_lookup_uint64_array(vdt, ZPOOL_CONFIG_VDEV_STATS, + (uint64_t **)&vds, &cnt); +#else + rv = nvlist_lookup_uint64_array(vdt, ZPOOL_CONFIG_STATS, + (uint64_t **)&vds, &cnt); +#endif + if (rv == 0) { + memcpy(&zps->vds, vds, sizeof(zps->vds)); + zps->vdev_stats_fresh = 1; + } else { + __pmNotifyErr(LOG_ERR, + "Cannot get zpool stats for '%s': %d %d\n", + zpname, rv, oserror()); + zps->vdev_stats_fresh = 0; + } + } + +done: + zpool_close(zp); + return 0; +} + +void +zpool_refresh(void) +{ + zp_added = 0; + + pmdaCacheOp(indomtab[ZPOOL_INDOM].it_indom, PMDA_CACHE_INACTIVE); + zpool_iter(zh, zp_cache_pool, NULL); + + if (zp_added) { + pmdaCacheOp(indomtab[ZPOOL_INDOM].it_indom, PMDA_CACHE_SAVE); + } +} + +int +zpool_fetch(pmdaMetric *pm, int inst, pmAtomValue *atom) +{ + struct zpool_stats *zps; + char *zpname; + metricdesc_t *md = pm->m_user; + + if (pmdaCacheLookup(indomtab[ZPOOL_INDOM].it_indom, inst, &zpname, + (void **)&zps) != PMDA_CACHE_ACTIVE) + return PM_ERR_INST; + + if (zps->vdev_stats_fresh) { + switch (pmid_item(md->md_desc.pmid)) { + case 0: /* zpool.state */ + atom->cp = zpool_state_to_name(zps->vds.vs_state, zps->vds.vs_aux); + break; + case 1: /* zpool.state_int */ + atom->ul = (zps->vds.vs_aux << 8) | zps->vds.vs_state; + break; + default: + memcpy(&atom->ull, ((char *)&zps->vds) + md->md_offset, + sizeof(atom->ull)); + } + } + return zps->vdev_stats_fresh; +} + +void +zpool_init(int first) +{ + if (zh) + return; + + zh = libzfs_init(); + if (zh) { + pmdaCacheOp(indomtab[ZPOOL_INDOM].it_indom, PMDA_CACHE_LOAD); + zpool_iter(zh, zp_cache_pool, NULL); + pmdaCacheOp(indomtab[ZPOOL_INDOM].it_indom, PMDA_CACHE_SAVE); + } +} |