/* * 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; }