Hi Christophe, HP asked me to implement cciss support for multipathing. Apparently their newer HBAs are multipathing capable. However, I have no idea about the failover method they're using; so I used multibus as a default. Maybe someone from HP can comment on this. There were several patches floating around which tried to achieve the same but given that they're trying to access /sys/block/cciss!cXdY/device (which doesn't exist for cciss) I doubt they'll do anything sensible. Please commit. Cheers, Hannes -- Dr. Hannes Reinecke zSeries & Storage hare@xxxxxxx +49 911 74053 688 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: Markus Rex, HRB 16746 (AG Nürnberg)
tree df9be98603906572e64ce368beb37befe7e17fd8 parent 384e85dfd13c58cfa9ef752aed1530b46116119d author Hannes Reinecke <hare@xxxxxxx> 1184584249 +0200 committer Hannes Reinecke <hare@xxxxxxx> 1184584249 +0200 libmultipath: Add support for cciss devices This patch enables multipath support for cciss devices. Signed-off-by: Hannes Reinecke <hare@xxxxxxx> 85dd54f10fb296c609b5537e802b491b167ca02f libmultipath/blacklist.c | 8 +--- libmultipath/discovery.c | 101 ++++++++++++++++++++++++++++++++++++++++++--- libmultipath/hwtable.c | 16 +++++++ libmultipath/structs.h | 1 + 4 files changed, 112 insertions(+), 14 deletions(-) diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c index 82a6a58..92ddec6 100644 --- a/libmultipath/blacklist.c +++ b/libmultipath/blacklist.c @@ -114,12 +114,6 @@ setup_default_blist (struct config * conf) return 1; if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT)) return 1; - - str = STRDUP("^cciss!c[0-9]d[0-9]*"); - if (!str) - return 1; - if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT)) - return 1; vector_foreach_slot (conf->hwtable, hwe, i) { if (hwe->bl_product) { @@ -136,7 +130,7 @@ setup_default_blist (struct config * conf) } } } - + return 0; } diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index e3d4cd5..6219973 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -70,9 +70,11 @@ path_discover (vector pathvec, struct config * conf, char * devname, int flag) condlog(0, "path too small"); return 1; } - - if (!filepresent(path)) + + if (strncmp(devname,"cciss",5) && !filepresent(path)) { + condlog(4, "path %s not present", path); return 0; + } pp = find_path_by_dev(pathvec, devname); @@ -207,12 +209,18 @@ sysfs_get_fc_nodename (struct sysfs_device * dev, char * node, static int opennode (char * dev, int mode) { - char devpath[FILE_NAME_SIZE]; + char devpath[FILE_NAME_SIZE], *ptr; if (safe_sprintf(devpath, "%s/%s", conf->udev_dir, dev)) { condlog(0, "devpath too small"); return -1; } + /* Translate '!' into '/' */ + ptr = devpath; + while ((ptr = strchr(ptr, '!'))) { + *ptr = '/'; + ptr++; + } return open(devpath, mode); } @@ -342,6 +350,27 @@ get_serial (char * str, int maxlen, int fd) } static int +get_inq (char * vendor, char * product, char * rev, int fd) +{ + int len = 0; + char buff[MX_ALLOC_LEN + 1] = {0}; + + if (fd < 0) + return 1; + + if (0 == do_inq(fd, 0, 0, 0, buff, MX_ALLOC_LEN, 0)) { + memcpy(vendor, buff + 8, 8); + vendor[8] = '\0'; + memcpy(product, buff + 16, 16); + product[16] = '\0'; + memcpy(rev, buff + 32, 4); + rev[4] = '\0'; + return 0; + } + return 1; +} + +static int scsi_sysfs_pathinfo (struct path * pp, struct sysfs_device * parent) { char attr_path[FILE_NAME_SIZE]; @@ -445,6 +474,31 @@ ccw_sysfs_pathinfo (struct path * pp, struct sysfs_device * parent) } static int +cciss_sysfs_pathinfo (struct path * pp, struct sysfs_device * dev) +{ + char attr_path[FILE_NAME_SIZE]; + char attr_buff[FILE_NAME_SIZE]; + + /* + * host / bus / target / lun + */ + basename(dev->devpath, attr_path); + pp->sg_id.lun = 0; + pp->sg_id.channel = 0; + sscanf(attr_path, "cciss!c%id%i", + &pp->sg_id.host_no, + &pp->sg_id.scsi_id); + condlog(3, "%s: h:b:t:l = %i:%i:%i:%i", + pp->dev, + pp->sg_id.host_no, + pp->sg_id.channel, + pp->sg_id.scsi_id, + pp->sg_id.lun); + + return 0; +} + +static int common_sysfs_pathinfo (struct path * pp, struct sysfs_device *dev) { char *attr; @@ -486,18 +540,22 @@ sysfs_pathinfo(struct path * pp) condlog(1, "%s: failed to get sysfs information", pp->dev); return 1; } - - parent = sysfs_device_get_parent(pp->sysdev); if (common_sysfs_pathinfo(pp, pp->sysdev)) return 1; + parent = sysfs_device_get_parent(pp->sysdev); + if (!parent) + parent = pp->sysdev; + condlog(3, "%s: subsystem = %s", pp->dev, parent->subsystem); if (!strncmp(parent->subsystem, "scsi",4)) pp->bus = SYSFS_BUS_SCSI; if (!strncmp(parent->subsystem, "ccw",3)) pp->bus = SYSFS_BUS_CCW; + if (!strncmp(pp->dev,"cciss",5)) + pp->bus = SYSFS_BUS_CCISS; if (pp->bus == SYSFS_BUS_UNDEF) return 0; @@ -507,6 +565,9 @@ sysfs_pathinfo(struct path * pp) } else if (pp->bus == SYSFS_BUS_CCW) { if (ccw_sysfs_pathinfo(pp, parent)) return 1; + } else if (pp->bus == SYSFS_BUS_CCISS) { + if (cciss_sysfs_pathinfo(pp, pp->sysdev)) + return 1; } return 0; } @@ -523,6 +584,25 @@ scsi_ioctl_pathinfo (struct path * pp, int mask) } static int +cciss_ioctl_pathinfo (struct path * pp, int mask) +{ + if (mask & DI_SYSFS) { + get_inq(pp->vendor_id, pp->product_id, pp->rev, pp->fd); + condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id); + condlog(3, "%s: product = %s", pp->dev, pp->product_id); + condlog(3, "%s: revision = %s", pp->dev, pp->rev); + /* + * set the hwe configlet pointer + */ + pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, + pp->product_id, pp->rev); + + } + + return 0; +} + +static int get_state (struct path * pp) { struct checker * c = &pp->checker; @@ -610,16 +690,23 @@ pathinfo (struct path *pp, vector hwtable, int mask) if (pp->fd < 0) pp->fd = opennode(pp->dev, O_RDONLY); - if (pp->fd < 0) + if (pp->fd < 0) { + condlog(4, "Couldn't open node for %s: %s", + pp->dev, strerror(errno)); goto blank; + } if (pp->bus == SYSFS_BUS_SCSI && scsi_ioctl_pathinfo(pp, mask)) goto blank; + if (pp->bus == SYSFS_BUS_CCISS && + cciss_ioctl_pathinfo(pp, mask)) + goto blank; + if (mask & DI_CHECKER && get_state(pp)) goto blank; - + /* * Retrieve path priority even for not PATH_UP paths if it has never * been successfully obtained before. diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c index 356e184..fb1a808 100644 --- a/libmultipath/hwtable.c +++ b/libmultipath/hwtable.c @@ -153,6 +153,22 @@ static struct hwentry default_hw[] = { .minio = DEFAULT_MINIO, .checker_name = TUR, }, + { + /* HP Smart Array */ + .vendor = "HP", + .product = "LOGICAL VOLUME.*", + .getuid = "/lib/udev/scsi_id -n -g -u -s /block/%n", + .getprio = NULL, + .features = DEFAULT_FEATURES, + .hwhandler = DEFAULT_HWHANDLER, + .selector = DEFAULT_SELECTOR, + .pgpolicy = MULTIBUS, + .pgfailback = FAILBACK_UNDEF, + .rr_weight = RR_WEIGHT_NONE, + .no_path_retry = NO_PATH_RETRY_UNDEF, + .minio = DEFAULT_MINIO, + .checker_name = TUR, + }, /* * DDN controller family * diff --git a/libmultipath/structs.h b/libmultipath/structs.h index 75322aa..f821f87 100644 --- a/libmultipath/structs.h +++ b/libmultipath/structs.h @@ -46,6 +46,7 @@ enum sysfs_buses { SYSFS_BUS_SCSI, SYSFS_BUS_IDE, SYSFS_BUS_CCW, + SYSFS_BUS_CCISS, }; enum pathstates {
-- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel