/*
 * Disk S.M.A.R.T Data PMDA
 *
 * Copyright (c) 2018 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 "pmda.h"
#include "domain.h"

#include "pmdasmart.h"

static int _isDSO = 1; /* for local contexts */
static char *smart_setup_lsblk;

pmdaIndom indomtable[] = {
	{ .it_indom = DISK_INDOM },
};

#define INDOM(x) (indomtable[x].it_indom)

/*
 * All metrics supported by this PMDA - one table entry for each metric
 */
pmdaMetric metrictable[] = {
	/* General device information */
	{ .m_desc = {
		PMDA_PMID(CLUSTER_DEVICE_INFO, HEALTH),
		PM_TYPE_STRING, DISK_INDOM, PM_SEM_DISCRETE,
		PMDA_PMUNITS(0,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_DEVICE_INFO, MODEL_FAMILY),
		PM_TYPE_STRING, DISK_INDOM, PM_SEM_DISCRETE,
		PMDA_PMUNITS(0,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_DEVICE_INFO, DEVICE_MODEL),
		PM_TYPE_STRING, DISK_INDOM, PM_SEM_DISCRETE,
		PMDA_PMUNITS(0,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_DEVICE_INFO, SERIAL_NUMBER),
		PM_TYPE_STRING, DISK_INDOM, PM_SEM_DISCRETE,
		PMDA_PMUNITS(0,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_DEVICE_INFO, CAPACITY_BYTES),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_DISCRETE,
		PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_DEVICE_INFO, SECTOR_SIZE),
		PM_TYPE_STRING, DISK_INDOM, PM_SEM_DISCRETE,
		PMDA_PMUNITS(0,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_DEVICE_INFO, ROTATION_RATE),
		PM_TYPE_STRING, DISK_INDOM, PM_SEM_DISCRETE,
		PMDA_PMUNITS(0,0,0,0,0,0) }, },
	/* Smart Attribute metrics */
	{ .m_desc = {
		PMDA_PMID(CLUSTER_RAW_READ_ERROR_RATE, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_RAW_READ_ERROR_RATE, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_RAW_READ_ERROR_RATE, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_RAW_READ_ERROR_RATE, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_RAW_READ_ERROR_RATE, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_THROUGHPUT_PERFORMANCE, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_THROUGHPUT_PERFORMANCE, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_THROUGHPUT_PERFORMANCE, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_THROUGHPUT_PERFORMANCE, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_THROUGHPUT_PERFORMANCE, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SPIN_UP_TIME, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SPIN_UP_TIME, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SPIN_UP_TIME, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SPIN_UP_TIME, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SPIN_UP_TIME, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_START_STOP_COUNT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_START_STOP_COUNT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_START_STOP_COUNT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_START_STOP_COUNT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_START_STOP_COUNT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REALLOCATED_SECTOR_COUNT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REALLOCATED_SECTOR_COUNT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REALLOCATED_SECTOR_COUNT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REALLOCATED_SECTOR_COUNT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REALLOCATED_SECTOR_COUNT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SEEK_ERROR_COUNT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SEEK_ERROR_COUNT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SEEK_ERROR_COUNT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SEEK_ERROR_COUNT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SEEK_ERROR_COUNT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SEEK_TIME_PERFORMANCE, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SEEK_TIME_PERFORMANCE, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SEEK_TIME_PERFORMANCE, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SEEK_TIME_PERFORMANCE, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SEEK_TIME_PERFORMANCE, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_ON_HOURS, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_ON_HOURS, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_ON_HOURS, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_ON_HOURS, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_ON_HOURS, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SPIN_RETRY_COUNT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SPIN_RETRY_COUNT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SPIN_RETRY_COUNT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SPIN_RETRY_COUNT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SPIN_RETRY_COUNT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CALIBRATION_RETRY_COUNT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CALIBRATION_RETRY_COUNT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CALIBRATION_RETRY_COUNT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CALIBRATION_RETRY_COUNT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CALIBRATION_RETRY_COUNT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_CYCLE_COUNT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_CYCLE_COUNT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_CYCLE_COUNT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_CYCLE_COUNT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_CYCLE_COUNT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_READ_SOFT_ERROR_RATE, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_READ_SOFT_ERROR_RATE, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_READ_SOFT_ERROR_RATE, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_READ_SOFT_ERROR_RATE, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_READ_SOFT_ERROR_RATE, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CURRENT_HELIUM_LEVEL, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CURRENT_HELIUM_LEVEL, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CURRENT_HELIUM_LEVEL, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CURRENT_HELIUM_LEVEL, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CURRENT_HELIUM_LEVEL, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_ERASE_FAIL_COUNT_CHIP, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_ERASE_FAIL_COUNT_CHIP, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_ERASE_FAIL_COUNT_CHIP, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_ERASE_FAIL_COUNT_CHIP, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_ERASE_FAIL_COUNT_CHIP, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_WEAR_LEVELING_COUNT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_WEAR_LEVELING_COUNT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_WEAR_LEVELING_COUNT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_WEAR_LEVELING_COUNT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_WEAR_LEVELING_COUNT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_USED_RESERVED_BLOCK_COUNT_TOTAL, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_USED_RESERVED_BLOCK_COUNT_TOTAL, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_USED_RESERVED_BLOCK_COUNT_TOTAL, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_USED_RESERVED_BLOCK_COUNT_TOTAL, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_USED_RESERVED_BLOCK_COUNT_TOTAL, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_UNUSED_RESERVED_BLOCK_COUNT_TOTAL, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_UNUSED_RESERVED_BLOCK_COUNT_TOTAL, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_UNUSED_RESERVED_BLOCK_COUNT_TOTAL, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_UNUSED_RESERVED_BLOCK_COUNT_TOTAL, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_UNUSED_RESERVED_BLOCK_COUNT_TOTAL, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_PROGRAM_FAIL_COUNT_TOTAL, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_PROGRAM_FAIL_COUNT_TOTAL, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_PROGRAM_FAIL_COUNT_TOTAL, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_PROGRAM_FAIL_COUNT_TOTAL, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_PROGRAM_FAIL_COUNT_TOTAL, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_ERASE_FAIL_COUNT_TOTAL, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_ERASE_FAIL_COUNT_TOTAL, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_ERASE_FAIL_COUNT_TOTAL, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_ERASE_FAIL_COUNT_TOTAL, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_ERASE_FAIL_COUNT_TOTAL, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_RUNTIME_BAD_BLOCK, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_RUNTIME_BAD_BLOCK, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_RUNTIME_BAD_BLOCK, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_RUNTIME_BAD_BLOCK, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_RUNTIME_BAD_BLOCK, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_END_TO_END_ERROR, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_END_TO_END_ERROR, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_END_TO_END_ERROR, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_END_TO_END_ERROR, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_END_TO_END_ERROR, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REPORTED_UNCORRECT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REPORTED_UNCORRECT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REPORTED_UNCORRECT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REPORTED_UNCORRECT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REPORTED_UNCORRECT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_COMMAND_TIMEOUT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_COMMAND_TIMEOUT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_COMMAND_TIMEOUT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_COMMAND_TIMEOUT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_COMMAND_TIMEOUT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HIGH_FLY_WRITES, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HIGH_FLY_WRITES, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HIGH_FLY_WRITES, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HIGH_FLY_WRITES, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HIGH_FLY_WRITES, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_AIRFLOW_TEMP_CELSIUS, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_AIRFLOW_TEMP_CELSIUS, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_AIRFLOW_TEMP_CELSIUS, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_AIRFLOW_TEMP_CELSIUS, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_AIRFLOW_TEMP_CELSIUS, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_G_SENSE_ERROR_RATE, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_G_SENSE_ERROR_RATE, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_G_SENSE_ERROR_RATE, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_G_SENSE_ERROR_RATE, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_G_SENSE_ERROR_RATE, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_OFF_RETRACT_COUNT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_OFF_RETRACT_COUNT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_OFF_RETRACT_COUNT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_OFF_RETRACT_COUNT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_POWER_OFF_RETRACT_COUNT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_CYCLE_COUNT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_CYCLE_COUNT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_CYCLE_COUNT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_CYCLE_COUNT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_CYCLE_COUNT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TEMPERATURE_CELSIUS, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TEMPERATURE_CELSIUS, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TEMPERATURE_CELSIUS, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TEMPERATURE_CELSIUS, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TEMPERATURE_CELSIUS, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HARDWARE_ECC_RECOVERED, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HARDWARE_ECC_RECOVERED, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HARDWARE_ECC_RECOVERED, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HARDWARE_ECC_RECOVERED, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HARDWARE_ECC_RECOVERED, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REALLOCATED_EVENT_COUNT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REALLOCATED_EVENT_COUNT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REALLOCATED_EVENT_COUNT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REALLOCATED_EVENT_COUNT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_REALLOCATED_EVENT_COUNT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CURRENT_PENDING_SECTOR, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CURRENT_PENDING_SECTOR, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CURRENT_PENDING_SECTOR, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CURRENT_PENDING_SECTOR, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_CURRENT_PENDING_SECTOR, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_OFFLINE_UNCORRECTABLE, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_OFFLINE_UNCORRECTABLE, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_OFFLINE_UNCORRECTABLE, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_OFFLINE_UNCORRECTABLE, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_OFFLINE_UNCORRECTABLE, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_UDMA_CRC_ERROR_COUNT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_UDMA_CRC_ERROR_COUNT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_UDMA_CRC_ERROR_COUNT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_UDMA_CRC_ERROR_COUNT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_UDMA_CRC_ERROR_COUNT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_MULTI_ZONE_ERROR_RATE, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_MULTI_ZONE_ERROR_RATE, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_MULTI_ZONE_ERROR_RATE, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_MULTI_ZONE_ERROR_RATE, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_MULTI_ZONE_ERROR_RATE, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SOFT_READ_ERROR_RATE, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SOFT_READ_ERROR_RATE, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SOFT_READ_ERROR_RATE, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SOFT_READ_ERROR_RATE, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_SOFT_READ_ERROR_RATE, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_DISK_SHIFT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_DISK_SHIFT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_DISK_SHIFT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_DISK_SHIFT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_DISK_SHIFT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOADED_HOURS, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOADED_HOURS, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOADED_HOURS, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOADED_HOURS, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOADED_HOURS, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_RETRY_COUNT, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_RETRY_COUNT, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_RETRY_COUNT, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_RETRY_COUNT, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_RETRY_COUNT, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_FRICTION, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_FRICTION, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_FRICTION, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_FRICTION, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_FRICTION, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_CYCLE, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_CYCLE, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_CYCLE, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_CYCLE, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_CYCLE, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_IN_TIME, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_IN_TIME, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_IN_TIME, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_IN_TIME, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_LOAD_IN_TIME, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HEAD_FLYING_HOURS, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HEAD_FLYING_HOURS, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HEAD_FLYING_HOURS, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HEAD_FLYING_HOURS, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_HEAD_FLYING_HOURS, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TOTAL_LBAS_WRITTEN, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TOTAL_LBAS_WRITTEN, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TOTAL_LBAS_WRITTEN, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TOTAL_LBAS_WRITTEN, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TOTAL_LBAS_WRITTEN, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TOTAL_LBAS_READ, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TOTAL_LBAS_READ, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TOTAL_LBAS_READ, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TOTAL_LBAS_READ, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_TOTAL_LBAS_READ, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_READ_ERROR_RETRY_RATE, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_READ_ERROR_RETRY_RATE, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_READ_ERROR_RETRY_RATE, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_READ_ERROR_RETRY_RATE, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_READ_ERROR_RETRY_RATE, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_FREE_FALL_SENSOR, SMART_ID),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_FREE_FALL_SENSOR, SMART_VALUE),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_FREE_FALL_SENSOR, SMART_WORST),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_FREE_FALL_SENSOR, SMART_THRESH),
		PM_TYPE_U32, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(1,0,0,0,0,0) }, },
	{ .m_desc = {
		PMDA_PMID(CLUSTER_FREE_FALL_SENSOR, SMART_RAW),
		PM_TYPE_U64, DISK_INDOM, PM_SEM_INSTANT,
		PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
};

int
metrictable_size(void)
{
	return sizeof(metrictable)/sizeof(metrictable[0]);
}

static int
smart_instance_refresh(void)
{
	int sts;
	char buffer[4096], dev_name[128];
	FILE *pf;
	pmInDom indom = INDOM(DISK_INDOM);

	/*
	 * update indom cache based off number of disks reported by "lsblk",
	 * smartctl requires us to know the block device id/path for each of 
	 * our disks in order to be able to get our stats, we get this info
	 * using "lsblk" and store the name of each device. 
	 */

	pmdaCacheOp(indom, PMDA_CACHE_INACTIVE);

	if ((pf = popen(smart_setup_lsblk, "r")) == NULL)
		return -oserror();

	while (fgets(buffer, sizeof(buffer)-1, pf)) {	
		sscanf(buffer, "%s", dev_name);
		buffer[sizeof(dev_name)-1] = '\0';

		/* at this point dev_name contains our device name this will be used to
		   map stats to disk drive instances */

		struct block_dev *dev;

		sts = pmdaCacheLookupName(indom, dev_name, NULL, (void **)&dev);
		if (sts == PM_ERR_INST || (sts >=0 && dev == NULL)) {
			dev = calloc(1, sizeof(struct block_dev));
			if (dev == NULL) {
				pclose(pf);
				return PM_ERR_AGAIN;
			}
		}
		else if (sts < 0)
			continue;

		pmdaCacheStore(indom, PMDA_CACHE_ADD, dev_name, (void *)dev);
	}

	pclose(pf);
	return(0);	
}

static int
smart_instance(pmInDom indom, int inst, char *name, pmInResult **result, pmdaExt *pmda)
{
	smart_instance_refresh();
	return pmdaInstance(indom, inst, name, result, pmda);
}

static int
smart_fetch_refresh(pmdaExt *pmda, int *need_refresh)
{
	pmInDom indom = INDOM(DISK_INDOM);
	struct block_dev *dev;
	char *dev_name;
	int i, sts;

	if ((sts = smart_instance_refresh()) < 0)
		return sts;

	for (pmdaCacheOp(indom, PMDA_CACHE_WALK_REWIND);;) {
		if ((i= pmdaCacheOp(indom, PMDA_CACHE_WALK_NEXT)) < 0)
			break;
		if (!pmdaCacheLookup(indom, i, &dev_name, (void **)&dev) || !dev)
			continue;

		if (need_refresh[CLUSTER_DEVICE_INFO])
			smart_refresh_device_info(dev_name, &dev->device_info);

		if (need_refresh[CLUSTER_RAW_READ_ERROR_RATE] ||
			need_refresh[CLUSTER_THROUGHPUT_PERFORMANCE] ||
			need_refresh[CLUSTER_SPIN_UP_TIME] ||
			need_refresh[CLUSTER_START_STOP_COUNT] ||
			need_refresh[CLUSTER_REALLOCATED_SECTOR_COUNT] ||
			need_refresh[CLUSTER_SEEK_ERROR_COUNT] ||
			need_refresh[CLUSTER_SEEK_TIME_PERFORMANCE] ||
			need_refresh[CLUSTER_POWER_ON_HOURS] ||
			need_refresh[CLUSTER_SPIN_RETRY_COUNT] ||
			need_refresh[CLUSTER_CALIBRATION_RETRY_COUNT] ||
			need_refresh[CLUSTER_POWER_CYCLE_COUNT] ||
			need_refresh[CLUSTER_READ_SOFT_ERROR_RATE] ||
			need_refresh[CLUSTER_CURRENT_HELIUM_LEVEL] ||
			need_refresh[CLUSTER_ERASE_FAIL_COUNT_CHIP] ||
			need_refresh[CLUSTER_WEAR_LEVELING_COUNT] ||
			need_refresh[CLUSTER_USED_RESERVED_BLOCK_COUNT_TOTAL] ||
			need_refresh[CLUSTER_UNUSED_RESERVED_BLOCK_COUNT_TOTAL] ||
			need_refresh[CLUSTER_PROGRAM_FAIL_COUNT_TOTAL] ||
			need_refresh[CLUSTER_ERASE_FAIL_COUNT_TOTAL] ||
			need_refresh[CLUSTER_RUNTIME_BAD_BLOCK] ||
			need_refresh[CLUSTER_END_TO_END_ERROR] ||
			need_refresh[CLUSTER_REPORTED_UNCORRECT] ||
			need_refresh[CLUSTER_COMMAND_TIMEOUT] ||
			need_refresh[CLUSTER_HIGH_FLY_WRITES] ||
			need_refresh[CLUSTER_AIRFLOW_TEMP_CELSIUS] ||
			need_refresh[CLUSTER_G_SENSE_ERROR_RATE] ||
			need_refresh[CLUSTER_POWER_OFF_RETRACT_COUNT] ||
			need_refresh[CLUSTER_LOAD_CYCLE_COUNT] ||
			need_refresh[CLUSTER_TEMPERATURE_CELSIUS] ||
			need_refresh[CLUSTER_HARDWARE_ECC_RECOVERED] ||
			need_refresh[CLUSTER_REALLOCATED_EVENT_COUNT] ||
			need_refresh[CLUSTER_CURRENT_PENDING_SECTOR] ||
			need_refresh[CLUSTER_OFFLINE_UNCORRECTABLE] ||
			need_refresh[CLUSTER_UDMA_CRC_ERROR_COUNT] ||
			need_refresh[CLUSTER_MULTI_ZONE_ERROR_RATE] ||
			need_refresh[CLUSTER_SOFT_READ_ERROR_RATE] ||
			need_refresh[CLUSTER_DISK_SHIFT] ||
			need_refresh[CLUSTER_LOADED_HOURS] ||
			need_refresh[CLUSTER_LOAD_RETRY_COUNT] ||
			need_refresh[CLUSTER_LOAD_FRICTION] ||
			need_refresh[CLUSTER_LOAD_CYCLE] ||
			need_refresh[CLUSTER_LOAD_IN_TIME] ||
			need_refresh[CLUSTER_HEAD_FLYING_HOURS] ||
			need_refresh[CLUSTER_TOTAL_LBAS_WRITTEN] ||
			need_refresh[CLUSTER_TOTAL_LBAS_READ] ||
			need_refresh[CLUSTER_READ_ERROR_RETRY_RATE] ||
			need_refresh[CLUSTER_FREE_FALL_SENSOR])
				smart_refresh_data(dev_name, &dev->smart_data);
	}
	return sts;
}

static int
smart_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda)
{
	int i, sts, need_refresh[NUM_CLUSTERS] = { 0 };

	for (i = 0; i < numpmid; i++) {
		unsigned int	cluster = pmID_cluster(pmidlist[i]);
		if (cluster < NUM_CLUSTERS)
		    need_refresh[cluster]++;
	}

	if ((sts = smart_fetch_refresh(pmda, need_refresh)) < 0)
		return sts;

	return pmdaFetch(numpmid, pmidlist, resp, pmda);
}

static int
smart_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom)
{
	unsigned int 		item = pmID_item(mdesc->m_desc.pmid);
	unsigned int		cluster = pmID_cluster(mdesc->m_desc.pmid);
	struct block_dev 	*dev;
	int 			sts;

	switch (cluster) {
		case CLUSTER_DEVICE_INFO:
			sts = pmdaCacheLookup(INDOM(DISK_INDOM), inst, NULL, (void **)&dev);
			if (sts < 0)
				return sts;
			return smart_device_info_fetch(item, &dev->device_info, atom);

		case CLUSTER_RAW_READ_ERROR_RATE:
		case CLUSTER_THROUGHPUT_PERFORMANCE:
		case CLUSTER_SPIN_UP_TIME:
		case CLUSTER_START_STOP_COUNT:
		case CLUSTER_REALLOCATED_SECTOR_COUNT:
		case CLUSTER_SEEK_ERROR_COUNT:
		case CLUSTER_SEEK_TIME_PERFORMANCE:
		case CLUSTER_POWER_ON_HOURS:
		case CLUSTER_SPIN_RETRY_COUNT:
		case CLUSTER_CALIBRATION_RETRY_COUNT:
		case CLUSTER_POWER_CYCLE_COUNT:
		case CLUSTER_READ_SOFT_ERROR_RATE:
		case CLUSTER_CURRENT_HELIUM_LEVEL:
		case CLUSTER_ERASE_FAIL_COUNT_CHIP:
		case CLUSTER_WEAR_LEVELING_COUNT:
		case CLUSTER_USED_RESERVED_BLOCK_COUNT_TOTAL:
		case CLUSTER_UNUSED_RESERVED_BLOCK_COUNT_TOTAL:
		case CLUSTER_PROGRAM_FAIL_COUNT_TOTAL:
		case CLUSTER_ERASE_FAIL_COUNT_TOTAL:
		case CLUSTER_RUNTIME_BAD_BLOCK:
		case CLUSTER_END_TO_END_ERROR:
		case CLUSTER_REPORTED_UNCORRECT:
		case CLUSTER_COMMAND_TIMEOUT:
		case CLUSTER_HIGH_FLY_WRITES:
		case CLUSTER_AIRFLOW_TEMP_CELSIUS:
		case CLUSTER_G_SENSE_ERROR_RATE:
		case CLUSTER_POWER_OFF_RETRACT_COUNT:
		case CLUSTER_LOAD_CYCLE_COUNT:
		case CLUSTER_TEMPERATURE_CELSIUS:
		case CLUSTER_HARDWARE_ECC_RECOVERED:
		case CLUSTER_REALLOCATED_EVENT_COUNT:
		case CLUSTER_CURRENT_PENDING_SECTOR:
		case CLUSTER_OFFLINE_UNCORRECTABLE:
		case CLUSTER_UDMA_CRC_ERROR_COUNT:
		case CLUSTER_MULTI_ZONE_ERROR_RATE:
		case CLUSTER_SOFT_READ_ERROR_RATE:
		case CLUSTER_DISK_SHIFT:
		case CLUSTER_LOADED_HOURS:
		case CLUSTER_LOAD_RETRY_COUNT:
		case CLUSTER_LOAD_FRICTION:
		case CLUSTER_LOAD_CYCLE:
		case CLUSTER_LOAD_IN_TIME:
		case CLUSTER_HEAD_FLYING_HOURS:
		case CLUSTER_TOTAL_LBAS_WRITTEN:
		case CLUSTER_TOTAL_LBAS_READ:
		case CLUSTER_READ_ERROR_RETRY_RATE:
		case CLUSTER_FREE_FALL_SENSOR:
			sts = pmdaCacheLookup(INDOM(DISK_INDOM), inst, NULL, (void **)&dev);
			if (sts < 0)
				return sts;
			return smart_data_fetch(item, cluster, &dev->smart_data, atom);

		default:
			return PM_ERR_PMID;
	}

	return PMDA_FETCH_STATIC;
}

void
smart_instance_setup(void)
{
	static char lsblk_command[] = "lsblk -d -n -e 1,2,7,11 -o name";
	char *env_command;

	/* allow override at startup for QA testing */
	if ((env_command = getenv("SMART_SETUP_LSBLK")) != NULL)
		smart_setup_lsblk = env_command;
	else
		smart_setup_lsblk = lsblk_command;
}

static int
smart_text(int ident, int type, char **buf, pmdaExt *pmda)
{
	if ((type & PM_TEXT_PMID) == PM_TEXT_PMID) {
		int sts = pmdaDynamicLookupText(ident, type, buf, pmda);
		if (sts != -ENOENT)
			return sts;
	}
	return pmdaText(ident, type, buf, pmda);
}

static int
smart_pmid(const char *name, pmID *pmid, pmdaExt *pmda)
{
	pmdaNameSpace *tree = pmdaDynamicLookupName(pmda, name);
	return pmdaTreePMID(tree, name, pmid);
}

static int
smart_name(pmID pmid, char ***nameset, pmdaExt *pmda)
{
	pmdaNameSpace *tree = pmdaDynamicLookupPMID(pmda, pmid);
	return pmdaTreeName(tree, pmid, nameset);
}

static int
smart_children(const char *name, int flag, char ***kids, int **sts, pmdaExt *pmda)
{
	pmdaNameSpace *tree = pmdaDynamicLookupName(pmda, name);
	return pmdaTreeChildren(tree, name, flag, kids, sts);
}

void
__PMDA_INIT_CALL
smart_init(pmdaInterface *dp)
{
	int nindoms = sizeof(indomtable)/sizeof(indomtable[0]);
	int nmetrics = sizeof(metrictable)/sizeof(metrictable[0]);

	if (_isDSO) {
		char helppath[MAXPATHLEN];
		int sep = pmPathSeparator();
		pmsprintf(helppath, sizeof(helppath), "%s%c" "smart" "%c" "help",
			pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
		pmdaDSO(dp, PMDA_INTERFACE_4, "SMART DSO", helppath);
	}

	if (dp->status != 0)
		return;

	/* Check for environment variables allowing test injection */
	smart_instance_setup();
	smart_stats_setup();

	dp->version.four.instance = smart_instance;
	dp->version.four.fetch = smart_fetch;
	dp->version.four.text = smart_text;
	dp->version.four.pmid = smart_pmid;
	dp->version.four.name = smart_name;
	dp->version.four.children = smart_children;
	pmdaSetFetchCallBack(dp, smart_fetchCallBack);

	pmdaSetFlags(dp, PMDA_EXT_FLAG_HASHED);
	pmdaInit(dp, indomtable, nindoms, metrictable, nmetrics);
}

static pmLongOptions longopts[] = {
	PMDA_OPTIONS_HEADER("Options"),
	PMOPT_DEBUG,
	PMDAOPT_DOMAIN,
	PMDAOPT_LOGFILE,
	PMOPT_HELP,
	PMDA_OPTIONS_END
};

static pmdaOptions opts = {
	.short_options = "D:d:l:U:?",
	.long_options = longopts,
};

int 
main(int argc, char **argv)
{
	int sep = pmPathSeparator();
	char helppath[MAXPATHLEN];
	pmdaInterface dispatch;

	_isDSO = 0;
	pmSetProgname(argv[0]);
	pmsprintf(helppath, sizeof(helppath), "%s%c" "smart" "%c" "help",
		pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
	pmdaDaemon(&dispatch, PMDA_INTERFACE_4, pmGetProgname(), SMART, "smart.log", helppath);

	pmdaGetOptions(argc, argv, &opts, &dispatch);
	if (opts.errors) {
		pmdaUsageMessage(&opts);
		exit(1);
	}

	pmdaOpenLog(&dispatch);

	smart_init(&dispatch);
	pmdaConnect(&dispatch);
	pmdaMain(&dispatch);
	exit(0);
}
