/*************************************************************************** * Copyright (C) 06/2010 by Olaf Rempel * * razzor@kopf-tisch.de * * * * 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. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include "configfile.h" #include "logging.h" #include "plugins.h" #include "probe.h" #include "sgio.h" int verbose = 0; int prefer_ata12 = 0; struct sammler_plugin plugin; struct device_entry { struct list_head list; char *devpath; }; static LIST_HEAD(device_list); static const char *ds_def = { "DS:active:GAUGE:90:0:1 " }; static const char * get_ds(int ds_id) { return ds_def; } static int probe(void) { struct device_entry *entry; list_for_each_entry(entry, &device_list, list) { int fd = open(entry->devpath, O_RDONLY|O_NONBLOCK); if (fd < 0) { log_print(LOG_ERROR, "%s: failed to open %s", plugin.name, entry->devpath); continue; } uint8_t args[4] = { ATA_OP_CHECKPOWERMODE1, 0, 0, 0 }; if (do_drive_cmd(fd, args)) { args[0] = ATA_OP_CHECKPOWERMODE2; if (do_drive_cmd(fd, args)) { log_print(LOG_ERROR, "%s: failed to query %s", plugin.name, entry->devpath); close(fd); continue; } } /* switch (args[2]) { case 0x00: state = "standby"; break; case 0x40: state = "NVcache_spindown"; break; case 0x41: state = "NVcache_spinup"; break; case 0x80: state = "idle"; break; case 0xff: state = "active/idle"; break; default: state = "unknown"; break; } */ char *dev = strrchr(entry->devpath, '/'); if (dev == NULL) { dev = entry->devpath; } else { dev++; } char filename[32]; int len = snprintf(filename, sizeof(filename), "diskstandby-%s.rrd", dev); if (len < 0 || len >= sizeof(filename)) continue; probe_submit(&plugin, filename, 0, "%u", (args[2] == 0xff) ? 1 : 0); close(fd); } return 0; } static int init_cb(struct strtoken *tokens, void *privdata) { if (tokens->count != 1) { log_print(LOG_ERROR, "%s: parse error", plugin.name); return -1; } struct device_entry *entry = malloc(sizeof(struct device_entry)); if (entry == NULL) { log_print(LOG_ERROR, "%s: out of memory", plugin.name); return -1; } entry->devpath = strdup(tokens->field[0]); log_print(LOG_INFO, "%s: added device '%s'", plugin.name, entry->devpath); list_add_tail(&entry->list, &device_list); return 0; } static int init(void) { config_get_strtokens("p_diskstandby", "device", ",", 1, init_cb, NULL); return 0; } static int fini(void) { struct device_entry *entry, *tmp; list_for_each_entry_safe(entry, tmp, &device_list, list) { free(entry->devpath); free(entry); } return 0; } struct sammler_plugin plugin = { .name = "diskstandby", .interval = 60, .init = &init, .fini = &fini, .probe = &probe, .get_ds = &get_ds, };