I commited this work as a starting point. Thank you Hannes. I hope to get an insight of what cciss multipathing means when the HP patchs start to flow ... multi-initiator SAS ? I'm interested :) Regards, cvaroqui Le lundi 16 juillet 2007 à 13:17 +0200, Hannes Reinecke a écrit : > 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 > pièce jointe document plein texte (multipath-tools-enable-cciss) > 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