mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Add an ability for ziorep_config tool to extract PCHID additional adapter parameter from .config file. With this patch device_info structure will have pchid field, which can be used by different printers classes. Also add function for querying PCHID by using of devno for providing reports. Translate "n/a" field from .config file record into invalid PCHID number. Signed-off-by: Fedor Loshakov <loshakov@linux.ibm.com> Reviewed-by: Sakshi Singh <005c7w@linux.ibm.com> Reviewed-by: M Nikhil <nikh1092@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
898 lines
20 KiB
C++
898 lines
20 KiB
C++
/*
|
|
* FCP report generators
|
|
*
|
|
* Utility classes to read and access FCP configuration information
|
|
*
|
|
* Copyright IBM Corp. 2008, 2024
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <assert.h>
|
|
|
|
#include "ziorep_cfgreader.hpp"
|
|
#include "ziorep_filters.hpp"
|
|
#include "ziorep_utils.hpp"
|
|
|
|
#define ZIOREP_CFG_EXTENSION ".cfg"
|
|
#define ZIOREP_CONFIG "ziorep_config"
|
|
|
|
extern const char *toolname;
|
|
extern int verbose;
|
|
|
|
|
|
ConfigReader::ConfigReader(int *rc, const char *filename)
|
|
: m_tmp_file(NULL), m_cfg_cached(false)
|
|
{
|
|
FILE *fp = NULL;
|
|
struct device_info new_elem;
|
|
char *line = NULL;
|
|
char *cfg_pchid = NULL;
|
|
size_t line_len;
|
|
int lrc;
|
|
int line_idx = 1;
|
|
long long unsigned int tmp_lun;
|
|
long long unsigned int tmp_wwpn;
|
|
unsigned int subch1, subch2, subch3, devno1, devno2, devno3;
|
|
|
|
*rc = 0;
|
|
|
|
if (check_config_file(filename)) {
|
|
*rc = -1;
|
|
return;
|
|
}
|
|
|
|
if (extract_config_data(filename)) {
|
|
*rc = -2;
|
|
return;
|
|
}
|
|
|
|
init_device_info(&new_elem);
|
|
|
|
verbose_msg("ConfigReader: reading from %s\n", m_tmp_file);
|
|
|
|
fp = fopen(m_tmp_file, "r");
|
|
if (!fp) {
|
|
fprintf(stderr, "%s: Could not open config file %s\n", toolname, m_tmp_file);
|
|
*rc = -1;
|
|
goto out_fp_not_opened;
|
|
}
|
|
while ( (lrc = getline(&line, &line_len, fp)) >= 0) {
|
|
// allocation could be improved...
|
|
init_device_info(&new_elem);
|
|
new_elem.device = (char*)malloc(lrc + 1);
|
|
new_elem.type = (char*)malloc(lrc + 1);
|
|
new_elem.multipath_device = (char*)malloc(lrc + 1);
|
|
cfg_pchid = (char*)malloc(lrc + 1);
|
|
lrc = sscanf(line, "%x %u:%u:%u:%u %x.%x.%x:%x.%x.%x:%Lx:%Lx %s %u %u:%u %s %u %u:%u %s %s",
|
|
&new_elem.chpid,
|
|
&new_elem.hctl_identifier.host,
|
|
&new_elem.hctl_identifier.channel,
|
|
&new_elem.hctl_identifier.target,
|
|
&new_elem.hctl_identifier.lun,
|
|
&subch1, &subch2, &subch3,
|
|
&devno1, &devno2, &devno3,
|
|
&tmp_wwpn,
|
|
&tmp_lun,
|
|
new_elem.multipath_device, &new_elem.mp_mm,
|
|
&new_elem.mp_major,
|
|
&new_elem.mp_minor, new_elem.device,
|
|
&new_elem.mm_internal,
|
|
&new_elem.major, &new_elem.minor,
|
|
new_elem.type,
|
|
cfg_pchid);
|
|
*rc = parse_pchid_str(cfg_pchid, &new_elem.pchid);
|
|
free(cfg_pchid);
|
|
free(line);
|
|
line = NULL;
|
|
if (lrc != 23 || *rc != 0) {
|
|
fprintf(stderr, "%s: Could not parse line %d"
|
|
" - configuration file broken?\n", toolname, line_idx);
|
|
*rc = -1;
|
|
goto out;
|
|
}
|
|
/* complete bus-IDs packed in u32 to avoid filter code changes */
|
|
new_elem.subchannel = ZIOREP_BUSID_PACKED(subch1, subch2, subch3);
|
|
new_elem.devno = ZIOREP_BUSID_PACKED(devno1, devno2, devno3);
|
|
new_elem.wwpn = tmp_wwpn;
|
|
new_elem.lun = tmp_lun;
|
|
|
|
if (strcmp(new_elem.multipath_device, "n/a") == 0) {
|
|
free(new_elem.multipath_device);
|
|
new_elem.multipath_device = NULL;
|
|
new_elem.mp_major = 0;
|
|
new_elem.mp_minor = 0;
|
|
}
|
|
m_devices.push_back(new_elem);
|
|
++line_idx;
|
|
}
|
|
init_device_info(&new_elem);
|
|
|
|
if (filter_unused_devices(filename)) {
|
|
*rc = -2;
|
|
goto out;
|
|
}
|
|
|
|
verbose_msg("ConfigReader: done\n");
|
|
|
|
out:
|
|
fclose(fp);
|
|
out_fp_not_opened:
|
|
free_device_info(&new_elem);
|
|
free(line);
|
|
|
|
if (m_tmp_file) {
|
|
if (!m_cfg_cached || *rc)
|
|
remove(m_tmp_file);
|
|
free(m_tmp_file);
|
|
m_tmp_file = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
ConfigReader::~ConfigReader()
|
|
{
|
|
for (list<struct device_info>::iterator i = m_devices.begin();
|
|
i != m_devices.end(); ++i)
|
|
free_device_info(&(*i));
|
|
}
|
|
|
|
|
|
int ConfigReader::filter_unused_devices(const char *filename)
|
|
{
|
|
DeviceFilter dev_filt;
|
|
int j = 0;
|
|
|
|
if (get_all_devices(filename, dev_filt, *this))
|
|
return -1;
|
|
|
|
for (list<struct device_info>::iterator i = m_devices.begin();
|
|
i != m_devices.end();) {
|
|
if (!dev_filt.is_eligible_mm((*i).mm_internal)) {
|
|
verbose_msg(" device %u:%u not in data, remove\n",
|
|
(*i).major, (*i).minor);
|
|
free_device_info(&(*i));
|
|
i = m_devices.erase(i);
|
|
j++;
|
|
}
|
|
else
|
|
++i;
|
|
}
|
|
verbose_msg("removed %d of %lu devices\n", j,
|
|
(long unsigned int)(m_devices.size() + j));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int ConfigReader::check_config_file(const char *fname) const
|
|
{
|
|
char *tmp;
|
|
int rc = 0;
|
|
|
|
tmp = (char*)malloc(strlen(fname) + strlen(ZIOREP_CFG_EXTENSION) + 1);
|
|
sprintf(tmp, "%s%s", fname, ZIOREP_CFG_EXTENSION);
|
|
|
|
if (access(tmp, F_OK | R_OK)) {
|
|
fprintf(stderr, "%s: Cannot access config file %s."
|
|
" Please make sure that you get the matching .cfg"
|
|
" file for your data.\n", toolname, tmp);
|
|
rc = -1;
|
|
}
|
|
free(tmp);
|
|
|
|
return rc;
|
|
}
|
|
|
|
#define ZIOREP_TMP_TEMPLATE "/tmp/ziorepXXXXXX"
|
|
#define ZIOREP_CONFIG_EXT ".config"
|
|
|
|
|
|
int ConfigReader::extract_config_data(const char *fname)
|
|
{
|
|
verbose_msg("Check config data...\n");
|
|
if (cached_config_exists(fname)) {
|
|
verbose_msg("Cached file found, reusing.\n");
|
|
m_cfg_cached = true;
|
|
return 0;
|
|
}
|
|
|
|
// Try to extract to .config first, which will be permanently cached
|
|
verbose_msg("No data cached, extract\n");
|
|
|
|
fprintf(stdout, "Extracting config data...");
|
|
fflush(stdout);
|
|
if (extract_cached(fname)) {
|
|
verbose_msg("Could not create %s file, create tmp file\n",
|
|
ZIOREP_CONFIG_EXT);
|
|
if (extract_tmp(fname)) {
|
|
fprintf(stderr, "%s: Could not extract"
|
|
" configuration data. Check the integrity of"
|
|
" %s%s with %s and retry.\n", toolname, fname,
|
|
ZIOREP_CFG_EXTENSION, ZIOREP_CONFIG);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
fprintf(stdout, "done\n");
|
|
|
|
verbose_msg("Check config data finished\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int ConfigReader::extract_cached(const char *fname)
|
|
{
|
|
assert(m_tmp_file == NULL);
|
|
|
|
m_tmp_file = (char*)malloc(strlen(fname) + strlen(ZIOREP_CONFIG_EXT)
|
|
+ 1);
|
|
sprintf(m_tmp_file, "%s%s", fname, ZIOREP_CONFIG_EXT);
|
|
|
|
if (extract(fname)) {
|
|
// we can't guarantee that something was not written,
|
|
// hence we remove the file anyway to avoid stumbling
|
|
// over a broken .config file next time
|
|
remove(m_tmp_file);
|
|
free(m_tmp_file);
|
|
m_tmp_file = NULL;
|
|
return -1;
|
|
}
|
|
m_cfg_cached = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int ConfigReader::extract_tmp(const char *fname)
|
|
{
|
|
int rc = 0;
|
|
|
|
assert(m_tmp_file == NULL);
|
|
|
|
m_tmp_file = (char*)malloc(strlen(ZIOREP_TMP_TEMPLATE) + 1);
|
|
strcpy(m_tmp_file, ZIOREP_TMP_TEMPLATE);
|
|
|
|
if (mkstemp(m_tmp_file) == -1) {
|
|
fprintf(stdout, "Error: Could not create temporary"
|
|
" filename: %s\n", strerror(errno));
|
|
rc = -1;
|
|
goto out;
|
|
}
|
|
|
|
rc = extract(fname);
|
|
|
|
out:
|
|
if (rc) {
|
|
free(m_tmp_file);
|
|
m_tmp_file = NULL;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
int ConfigReader::extract(const char *fname)
|
|
{
|
|
int rc = 0;
|
|
char *cmd = NULL;
|
|
|
|
// /sbin/ziorep_config -I -i <fname.cfg> > <file> 2>/dev/null
|
|
cmd = (char*)malloc(strlen(ZIOREP_CONFIG) + 7 + strlen(fname)
|
|
+ strlen(ZIOREP_CFG_EXTENSION) + 3 + strlen(m_tmp_file)
|
|
+ 12 + 1);
|
|
|
|
sprintf(cmd, "%s -I -i %s%s > %s 2>/dev/null", ZIOREP_CONFIG, fname,
|
|
ZIOREP_CFG_EXTENSION, m_tmp_file);
|
|
|
|
verbose_msg("Issue command: %s\n", cmd);
|
|
|
|
if (system(cmd)) {
|
|
rc = -1;
|
|
goto out;
|
|
}
|
|
verbose_msg("Data extracted to %s\n", m_tmp_file);
|
|
|
|
out:
|
|
free(cmd);
|
|
return rc;
|
|
}
|
|
|
|
|
|
bool ConfigReader::cached_config_exists(const char *fname)
|
|
{
|
|
int rc = true;
|
|
|
|
m_tmp_file = (char*)malloc(strlen(fname) + strlen(ZIOREP_CONFIG_EXT)
|
|
+ 1);
|
|
sprintf(m_tmp_file, "%s%s", fname, ZIOREP_CONFIG_EXT);
|
|
|
|
if (access(m_tmp_file, R_OK)) {
|
|
verbose_msg("No cached file found.\n");
|
|
free(m_tmp_file);
|
|
m_tmp_file = NULL;
|
|
rc = false;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
int ConfigReader::extract_adapter_info_sub(char **tgt, char *p, char delim)
|
|
{
|
|
int offset;
|
|
|
|
offset = get_index_to(p, delim);
|
|
if (offset <=0)
|
|
return -1;
|
|
*tgt = (char*)malloc(offset + 1);
|
|
strncpy(*tgt, p, offset);
|
|
(*tgt)[offset] = '\0';
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void ConfigReader::init_device_info(struct device_info *info)
|
|
{
|
|
info->multipath_device = NULL;
|
|
info->device = NULL;
|
|
info->type = NULL;
|
|
}
|
|
|
|
|
|
void ConfigReader::free_device_info(struct device_info *info)
|
|
{
|
|
free(info->multipath_device);
|
|
info->multipath_device = NULL;
|
|
free(info->device);
|
|
info->device = NULL;
|
|
free(info->type);
|
|
info->type = NULL;
|
|
}
|
|
|
|
|
|
int ConfigReader::get_index_to(char *p, char c) const
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; *p != c && *p != '\0'; ++p, ++i) ;
|
|
|
|
return i;
|
|
}
|
|
|
|
|
|
void ConfigReader::host_id_not_found_error(__u32 h, int *rc) const
|
|
{
|
|
*rc = -1;
|
|
fprintf(stderr, "%s: Could not find host index %u in configuration"
|
|
" file. Please check if you have the right .cfg file and try"
|
|
" again\n", toolname, h);
|
|
}
|
|
|
|
void ConfigReader::devno_not_found_error(__u32 devno, int *rc) const
|
|
{
|
|
*rc = -1;
|
|
fprintf(stderr, "%s: Could not find bus id %x.%x.%04x in configuration"
|
|
" file. Please check if you have the right .cfg file and try"
|
|
" again\n", toolname, ZIOREP_BUSID_UNPACKED(devno));
|
|
}
|
|
|
|
|
|
void ConfigReader::chpid_not_found_error(__u32 chpid, int *rc) const
|
|
{
|
|
*rc = -1;
|
|
fprintf(stderr, "%s: Could not find chpid %x in configuration"
|
|
" file. Please check if you have the right .cfg file and try"
|
|
" again\n", toolname, chpid);
|
|
}
|
|
|
|
|
|
void ConfigReader::lun_not_found_error(__u64 lun, int *rc) const
|
|
{
|
|
*rc = -1;
|
|
fprintf(stderr, "%s: Could not find LUN %016Lx in configuration"
|
|
" file. Please check if you have the right .cfg file and try"
|
|
" again\n", toolname, (long long unsigned int)lun);
|
|
}
|
|
|
|
|
|
void ConfigReader::ident_not_found_error(const struct hctl_ident *ident, int *rc) const
|
|
{
|
|
*rc = -1;
|
|
fprintf(stderr, "%s: Could not find identifier [%d:%d:%d:%d] in"
|
|
" configuration file. Please check if you have the right .cfg"
|
|
" file and try again\n", toolname, ident->host, ident->channel,
|
|
ident->target, ident->lun);
|
|
}
|
|
|
|
|
|
void ConfigReader::mm_internal_not_found_error(__u32 mm, int *rc) const
|
|
{
|
|
*rc = -1;
|
|
fprintf(stderr, "%s: Could not find device with internal mm %u in"
|
|
" configuration file. Please check if you have the right .cfg"
|
|
" file and try again\n", toolname, mm);
|
|
}
|
|
|
|
|
|
void ConfigReader::device_not_found_error(const char *dev, int *rc) const
|
|
{
|
|
*rc = -1;
|
|
fprintf(stderr, "%s: Could not find device %s in"
|
|
" configuration file. Please check if you have the right .cfg"
|
|
" file and try again\n", toolname, dev);
|
|
}
|
|
|
|
|
|
void ConfigReader::mp_not_found_error(const char *mp, int *rc) const
|
|
{
|
|
*rc = -1;
|
|
fprintf(stderr, "%s: Could not find multipath device %s in"
|
|
" configuration file. Please check if you have the right .cfg"
|
|
" file and try again\n", toolname, mp);
|
|
}
|
|
|
|
|
|
void ConfigReader::mp_mm_not_found_error(__u32 mp_mm, int *rc) const
|
|
{
|
|
*rc = -1;
|
|
fprintf(stderr, "%s: Could not find multipath device %ud in"
|
|
" configuration file. Please check if you have the right .cfg"
|
|
" file and try again\n", toolname, mp_mm);
|
|
}
|
|
|
|
|
|
#define search_for(att, crit, ret) for (list<struct device_info>::const_iterator i = m_devices.begin(); \
|
|
i != m_devices.end(); ++i) { \
|
|
if ((*i).att == crit) \
|
|
return (*i).ret; \
|
|
}
|
|
|
|
#define search_for_by_dev(crit, ret) for (list<struct device_info>::const_iterator i = m_devices.begin(); \
|
|
i != m_devices.end(); ++i) { \
|
|
if (compare_hctl_idents(&(*i).hctl_identifier, crit) == 0) \
|
|
return (*i).ret; \
|
|
}
|
|
|
|
__u32 ConfigReader::get_chpid_by_host_id(__u32 host, int *rc) const
|
|
{
|
|
search_for(hctl_identifier.host, host, chpid);
|
|
|
|
host_id_not_found_error(host, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
__u32 ConfigReader::get_pchid_by_host_id(__u32 host, int *rc) const
|
|
{
|
|
search_for(hctl_identifier.host, host, pchid);
|
|
|
|
host_id_not_found_error(host, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
__u32 ConfigReader::get_chpid_by_devno(__u32 d, int *rc) const
|
|
{
|
|
search_for(devno, d, chpid);
|
|
|
|
devno_not_found_error(d, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
__u32 ConfigReader::get_chpid_by_ident(const struct hctl_ident *ident, int *rc) const
|
|
{
|
|
search_for_by_dev(ident, chpid);
|
|
|
|
ident_not_found_error(ident, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
__u32 ConfigReader::get_chpid_by_mm_internal(__u32 mm, int *rc) const
|
|
{
|
|
search_for(mm_internal, mm, chpid);
|
|
|
|
mm_internal_not_found_error(mm, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
__u32 ConfigReader::get_host_id_by_chpid(__u32 chpid, int *rc) const
|
|
{
|
|
search_for(chpid, chpid, hctl_identifier.host);
|
|
|
|
chpid_not_found_error(chpid, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
__u32 ConfigReader::get_devno_by_host_id(__u32 host, int *rc) const
|
|
{
|
|
search_for(hctl_identifier.host, host, devno);
|
|
|
|
host_id_not_found_error(host, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
__u32 ConfigReader::get_devno_by_ident(const struct hctl_ident *ident,
|
|
int *rc) const
|
|
{
|
|
search_for_by_dev(ident, devno);
|
|
|
|
ident_not_found_error(ident, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
__u32 ConfigReader::get_devno_by_mm_internal(__u32 mm, int *rc) const
|
|
{
|
|
search_for(mm_internal, mm, devno);
|
|
|
|
mm_internal_not_found_error(mm, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
__u32 ConfigReader::get_mp_mm_by_multipath(const char* mp, int *rc) const
|
|
{
|
|
for (list<struct device_info>::const_iterator i = m_devices.begin();
|
|
i != m_devices.end(); ++i) {
|
|
if ((*i).multipath_device
|
|
&& strcmp((*i).multipath_device + strlen("/dev/mapper/"),
|
|
mp) == 0)
|
|
return (*i).mp_mm;
|
|
}
|
|
|
|
mp_not_found_error(mp, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
const char* ConfigReader::get_multipath_by_mp_mm(__u32 mp_mm, int *rc) const
|
|
{
|
|
search_for(mp_mm, mp_mm, multipath_device);
|
|
|
|
mp_mm_not_found_error(mp_mm, rc);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
__u64 ConfigReader::get_wwpn_by_mm_internal(__u32 dev, int *rc) const
|
|
{
|
|
search_for(mm_internal, dev, wwpn);
|
|
|
|
mm_internal_not_found_error(dev, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
__u64 ConfigReader::get_wwpn_by_ident(const struct hctl_ident *ident, int *rc) const
|
|
{
|
|
search_for_by_dev(ident, wwpn);
|
|
|
|
ident_not_found_error(ident, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
__u32 ConfigReader::get_mp_mm_by_mm_internal(__u32 mm, int *rc) const
|
|
{
|
|
search_for(mm_internal, mm, mp_mm);
|
|
|
|
mm_internal_not_found_error(mm, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
__u32 ConfigReader::get_mp_mm_by_ident(const struct hctl_ident *ident, int *rc) const
|
|
{
|
|
search_for_by_dev(ident, mp_mm);
|
|
|
|
ident_not_found_error(ident, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
__u64 ConfigReader::get_lun_by_mm_internal(__u32 mm, int *rc) const
|
|
{
|
|
search_for(mm_internal, mm, lun);
|
|
|
|
mm_internal_not_found_error(mm, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
const char* ConfigReader::get_dev_by_mm_internal(__u32 mm, int *rc) const
|
|
{
|
|
search_for(mm_internal, mm, device);
|
|
|
|
mm_internal_not_found_error(mm, rc);
|
|
|
|
return "<invalid device>";
|
|
}
|
|
|
|
__u32 ConfigReader::get_mm_by_ident(const struct hctl_ident *id, int *rc) const
|
|
{
|
|
search_for_by_dev(id, mm_internal);
|
|
|
|
ident_not_found_error(id, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
__u32 ConfigReader::get_mm_by_device(const char *dev, int *rc) const
|
|
{
|
|
for (list<struct device_info>::const_iterator i = m_devices.begin();
|
|
i != m_devices.end(); ++i) {
|
|
if (strcmp((*i).device + strlen("/dev/"), dev) == 0)
|
|
return (*i).mm_internal;
|
|
}
|
|
|
|
device_not_found_error(dev, rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
const struct hctl_ident* ConfigReader::get_ident_by_mm_internal(__u32 mm, int *rc) const
|
|
{
|
|
for (list<struct device_info>::const_iterator i = m_devices.begin();
|
|
i != m_devices.end(); ++i) {
|
|
if ((*i).mm_internal == mm)
|
|
return &(*i).hctl_identifier;
|
|
}
|
|
|
|
mm_internal_not_found_error(mm, rc);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
#define get_uniq(tgt, a, type) tgt.clear(); \
|
|
for (list<struct device_info>::const_iterator i = m_devices.begin(); \
|
|
i != m_devices.end(); ++i) { \
|
|
list<type>::iterator j; \
|
|
for (j = tgt.begin(); j != tgt.end() && (*i).a != (*j); ++j) \
|
|
; \
|
|
if (j == tgt.end()) \
|
|
tgt.push_back((*i).a); \
|
|
}
|
|
|
|
|
|
void ConfigReader::get_unique_wwpns(list<__u64> &wwpns) const
|
|
{
|
|
get_uniq(wwpns, wwpn, __u64);
|
|
}
|
|
|
|
|
|
void ConfigReader::get_unique_devnos(list<__u32> &devnos) const
|
|
{
|
|
get_uniq(devnos, devno, __u32);
|
|
}
|
|
|
|
|
|
void ConfigReader::get_unique_chpids(list<__u32> &chpids) const
|
|
{
|
|
get_uniq(chpids, chpid, __u32);
|
|
}
|
|
|
|
|
|
void ConfigReader::get_unique_host_ids(list<__u32> &host_ids) const
|
|
{
|
|
get_uniq(host_ids, hctl_identifier.host, __u32);
|
|
}
|
|
|
|
|
|
void ConfigReader::get_unique_mp_mms(list<__u32> &mp_mms) const
|
|
{
|
|
mp_mms.clear();
|
|
for (list<struct device_info>::const_iterator i = m_devices.begin();
|
|
i != m_devices.end(); ++i) {
|
|
list<__u32>::iterator j;
|
|
for (j = mp_mms.begin();
|
|
j != mp_mms.end() && (*i).mp_mm != (*j); ++j) ;
|
|
/* Watch out: Always check the multipath_device attribute
|
|
to see whether the mp_mm is valid or not! */
|
|
if (j == mp_mms.end() && (*i).multipath_device != NULL)
|
|
mp_mms.push_back((*i).mp_mm);
|
|
}
|
|
}
|
|
|
|
|
|
void ConfigReader::get_unique_mms(list<__u32> &lst) const
|
|
{
|
|
lst.clear();
|
|
for (list<struct device_info>::const_iterator i = m_devices.begin();
|
|
i != m_devices.end(); ++i)
|
|
// devices are unique by definition!
|
|
lst.push_back((*i).mm_internal);
|
|
}
|
|
|
|
|
|
void ConfigReader::get_unique_devices(list<struct hctl_ident> &idents) const
|
|
{
|
|
idents.clear();
|
|
for (list<struct device_info>::const_iterator i = m_devices.begin();
|
|
i != m_devices.end(); ++i) {
|
|
// devices are unique by definition!
|
|
idents.push_back((*i).hctl_identifier);
|
|
}
|
|
}
|
|
|
|
|
|
void ConfigReader::get_devnos_by_chpid(list<__u32> &devnos, __u32 chpid) const
|
|
{
|
|
devnos.clear();
|
|
for (list<struct device_info>::const_iterator i = m_devices.begin();
|
|
i != m_devices.end(); ++i) {
|
|
if ((*i).chpid == chpid)
|
|
devnos.push_back((*i).devno);
|
|
}
|
|
}
|
|
|
|
|
|
void ConfigReader::get_devnos_by_host_id(list<__u32> &devnos, __u32 host_id) const
|
|
{
|
|
devnos.clear();
|
|
for (list<struct device_info>::const_iterator i = m_devices.begin();
|
|
i != m_devices.end(); ++i) {
|
|
if ((*i).hctl_identifier.host == host_id)
|
|
devnos.push_back((*i).devno);
|
|
}
|
|
}
|
|
|
|
|
|
#define get_mms_list(lst, crit, val) lst.clear(); \
|
|
for (list<struct device_info>::const_iterator i = m_devices.begin(); \
|
|
i != m_devices.end(); ++i) { \
|
|
if ((*i).crit == val) \
|
|
lst.push_back((*i).mm_internal); \
|
|
} \
|
|
|
|
void ConfigReader::get_mms_by_chpid(list<__u32> &mms, __u32 chpid) const
|
|
{
|
|
get_mms_list(mms, chpid, chpid);
|
|
}
|
|
|
|
void ConfigReader::get_mms_by_mp_mm(list<__u32> &mms, __u32 mp_mm) const
|
|
{
|
|
get_mms_list(mms, mp_mm, mp_mm);
|
|
}
|
|
|
|
void ConfigReader::get_mms_by_wwpn(list<__u32> &mms, __u64 wwpn) const
|
|
{
|
|
get_mms_list(mms, wwpn, wwpn);
|
|
}
|
|
|
|
void ConfigReader::get_mms_by_devno(list<__u32> &mms, __u32 d) const
|
|
{
|
|
get_mms_list(mms, devno, d);
|
|
}
|
|
|
|
void ConfigReader::get_mms_by_lun(list<__u32> &mms, __u64 l) const
|
|
{
|
|
get_mms_list(mms, lun, l);
|
|
}
|
|
|
|
#define verify_numeric(criterion, val) for \
|
|
(list<struct device_info>::const_iterator \
|
|
i = m_devices.begin(); i != m_devices.end(); ++i) { \
|
|
if ((*i).criterion == val) \
|
|
return true; \
|
|
} \
|
|
return false;
|
|
|
|
|
|
#define verify_char(criterion, val, rc) for \
|
|
(list<struct device_info>::const_iterator \
|
|
i = m_devices.begin(); i != m_devices.end(); ++i) { \
|
|
if (val && (*i).criterion && strcmp((*i).criterion, val) == 0) \
|
|
rc = true; \
|
|
}
|
|
|
|
|
|
bool ConfigReader::verify_chpid(__u32 c) const
|
|
{
|
|
verify_numeric(chpid, c);
|
|
}
|
|
|
|
|
|
bool ConfigReader::verify_device(const char *dev) const
|
|
{
|
|
bool rc = false;
|
|
char *tmp;
|
|
|
|
tmp = (char*)malloc(strlen(dev) + strlen("/dev/") + 1);
|
|
sprintf(tmp, "/dev/%s", dev);
|
|
|
|
verify_char(device, tmp, rc);
|
|
|
|
free(tmp);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
bool ConfigReader::verify_mp_device(const char *mp) const
|
|
{
|
|
bool rc = false;
|
|
char *tmp;
|
|
|
|
tmp = (char*)malloc(strlen(mp) + strlen("/dev/mapper/") + 1);
|
|
sprintf(tmp, "/dev/mapper/%s", mp);
|
|
|
|
verify_char(multipath_device, tmp, rc);
|
|
|
|
free(tmp);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
bool ConfigReader::verify_wwpn(__u64 w) const
|
|
{
|
|
verify_numeric(wwpn, w);
|
|
}
|
|
|
|
|
|
bool ConfigReader::verify_devno(__u32 d) const
|
|
{
|
|
verify_numeric(devno, d);
|
|
}
|
|
|
|
|
|
bool ConfigReader::verify_lun(__u64 l) const
|
|
{
|
|
verify_numeric(lun, l);
|
|
}
|
|
|
|
|
|
void ConfigReader::dump(FILE *fp) const
|
|
{
|
|
fprintf(fp, "dumping cfg....\n");
|
|
for (list<struct device_info>::const_iterator i = m_devices.begin();
|
|
i != m_devices.end(); ++i) {
|
|
fprintf(fp, "%x %u %u:%u:%u:%u %x.%x.%04x:%x.%x.%04x:%016Lx:%016Lx %s %u:%u %s %u:%u %s %x\n",
|
|
(*i).chpid, (*i).mm_internal,
|
|
(*i).hctl_identifier.host,
|
|
(*i).hctl_identifier.channel,
|
|
(*i).hctl_identifier.target,
|
|
(*i).hctl_identifier.lun,
|
|
ZIOREP_BUSID_UNPACKED((*i).subchannel),
|
|
ZIOREP_BUSID_UNPACKED((*i).devno),
|
|
(long long unsigned int)(*i).wwpn,
|
|
(long long unsigned int)(*i).lun,
|
|
((*i).multipath_device ? (*i).multipath_device : "n/a"), (*i).mp_major,
|
|
(*i).mp_minor, (*i).device,
|
|
(*i).major, (*i).minor,
|
|
(*i).type,
|
|
(*i).pchid);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|