[dm-devel] Re: [libmultipath] Add cciss support
Christophe Varoqui
christophe.varoqui at free.fr
Mon Jul 30 22:09:27 UTC 2007
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 at suse.de> 1184584249 +0200
> committer Hannes Reinecke <hare at suse.de> 1184584249 +0200
>
> libmultipath: Add support for cciss devices
>
> This patch enables multipath support for cciss devices.
>
> Signed-off-by: Hannes Reinecke <hare at suse.de>
> 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 {
More information about the dm-devel
mailing list