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/linux/proc_scsi.c | |
download | pcp-debian/3.9.10.tar.gz |
Debian 3.9.10debian/3.9.10debian
Diffstat (limited to 'src/pmdas/linux/proc_scsi.c')
-rw-r--r-- | src/pmdas/linux/proc_scsi.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/pmdas/linux/proc_scsi.c b/src/pmdas/linux/proc_scsi.c new file mode 100644 index 0000000..2b3c952 --- /dev/null +++ b/src/pmdas/linux/proc_scsi.c @@ -0,0 +1,159 @@ +/* + * Linux Scsi Devices Cluster + * + * Copyright (c) 2014 Red Hat. + * Copyright (c) 2000,2004 Silicon Graphics, Inc. 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 "pmapi.h" +#include "impl.h" +#include "pmda.h" +#include "indom.h" +#include "proc_scsi.h" + +static char diskname[64]; +static char tapename[64]; +static char cdromname[64]; + +int +refresh_proc_scsi(proc_scsi_t *scsi) +{ + char buf[1024]; + char name[1024]; + int i; + int n; + FILE *fp; + char *sp; + static int have_devfs = -1; + static int next_id = -1; + + if (next_id < 0) { + /* one trip initialization */ + next_id = 0; + + scsi->nscsi = 0; + scsi->scsi = (scsi_entry_t *)malloc(sizeof(scsi_entry_t)); + + /* scsi indom */ + scsi->scsi_indom->it_numinst = 0; + scsi->scsi_indom->it_set = (pmdaInstid *)malloc(sizeof(pmdaInstid)); + + /* devfs naming convention */ + have_devfs = access("/dev/.devfsd", F_OK) == 0; + if (have_devfs) { + strcpy(diskname, "scsi/host%d/bus%d/target%d/lun%d/disc"); + strcpy(tapename, "st0"); + strcpy(cdromname, "scd0"); + } + else { + strcpy(diskname, "sda"); + strcpy(tapename, "st0"); + strcpy(cdromname, "scd0"); + } + } + + if ((fp = linux_statsfile("/proc/scsi/scsi", buf, sizeof(buf))) == NULL) + return -oserror(); + + while (fgets(buf, sizeof(buf), fp) != NULL) { + scsi_entry_t x = { 0 }; + + if (strncmp(buf, "Host:", 5) != 0) + continue; + + n = sscanf(buf, "Host: scsi%d Channel: %d Id: %d Lun: %d", + &x.dev_host, &x.dev_channel, &x.dev_id, &x.dev_lun); + if (n != 4) + continue; + for (i=0; i < scsi->nscsi; i++) { + if (scsi->scsi[i].dev_host == x.dev_host && + scsi->scsi[i].dev_channel == x.dev_channel && + scsi->scsi[i].dev_id == x.dev_id && + scsi->scsi[i].dev_lun == x.dev_lun) + break; + } + + if (i == scsi->nscsi) { + scsi->nscsi++; + scsi->scsi = (scsi_entry_t *)realloc(scsi->scsi, + scsi->nscsi * sizeof(scsi_entry_t)); + memcpy(&scsi->scsi[i], &x, sizeof(scsi_entry_t)); + scsi->scsi[i].id = next_id++; + /* scan for the Vendor: and Type: strings */ + while (fgets(buf, sizeof(buf), fp) != NULL) { + if ((sp = strstr(buf, "Type:")) != (char *)NULL) { + if (sscanf(sp, "Type: %s", name) == 1) + scsi->scsi[i].dev_type = strdup(name); + else + scsi->scsi[i].dev_type = strdup("unknown"); + break; + } + } + + if (strcmp(scsi->scsi[i].dev_type, "Direct-Access") == 0) { + if (have_devfs) { + scsi->scsi[i].dev_name = (char *)malloc(64); + sprintf(scsi->scsi[i].dev_name, diskname, + scsi->scsi[i].dev_host, scsi->scsi[i].dev_channel, + scsi->scsi[i].dev_id, scsi->scsi[i].dev_lun); + } + else { + scsi->scsi[i].dev_name = strdup(diskname); + diskname[2]++; /* sd[a-z] bump to next disk device name */ + } + } + else + if (strcmp(scsi->scsi[i].dev_type, "Sequential-Access") == 0) { + scsi->scsi[i].dev_name = strdup(tapename); + tapename[2]++; /* st[0-9] bump to next tape device name */ + } + else + if (strcmp(scsi->scsi[i].dev_type, "CD-ROM") == 0) { + scsi->scsi[i].dev_name = strdup(cdromname); + cdromname[3]++; /* scd[0-9] bump to next CDROM device name */ + } + else + if (strcmp(scsi->scsi[i].dev_type, "Processor") == 0) + scsi->scsi[i].dev_name = strdup("SCSI Controller"); + else + scsi->scsi[i].dev_name = strdup("Unknown SCSI device"); + + sprintf(name, "scsi%d:%d:%d:%d %s", scsi->scsi[i].dev_host, + scsi->scsi[i].dev_channel, scsi->scsi[i].dev_id, scsi->scsi[i].dev_lun, scsi->scsi[i].dev_type); + scsi->scsi[i].namebuf = strdup(name); +#if PCP_DEBUG + if (pmDebug & DBG_TRACE_LIBPMDA) { + fprintf(stderr, "refresh_proc_scsi: add host=scsi%d channel=%d id=%d lun=%d type=%s\n", + scsi->scsi[i].dev_host, scsi->scsi[i].dev_channel, + scsi->scsi[i].dev_id, scsi->scsi[i].dev_lun, + scsi->scsi[i].dev_type); + } +#endif + } + } + + /* refresh scsi indom */ + if (scsi->scsi_indom->it_numinst != scsi->nscsi) { + scsi->scsi_indom->it_numinst = scsi->nscsi; + scsi->scsi_indom->it_set = (pmdaInstid *)realloc(scsi->scsi_indom->it_set, + scsi->nscsi * sizeof(pmdaInstid)); + memset(scsi->scsi_indom->it_set, 0, scsi->nscsi * sizeof(pmdaInstid)); + } + for (i=0; i < scsi->nscsi; i++) { + scsi->scsi_indom->it_set[i].i_inst = scsi->scsi[i].id; + scsi->scsi_indom->it_set[i].i_name = scsi->scsi[i].namebuf; + } + + fclose(fp); + return 0; +} |