From mboxrd@z Thu Jan 1 00:00:00 1970 From: Harald Hoyer Date: Mon, 12 Jul 2010 09:16:42 +0000 Subject: Re: [PATCH] path_id: Handle SAS and SATA devices Message-Id: <4C3ADD7A.2010009@redhat.com> List-Id: References: <20100707145508.A42312A2B9@ochil.suse.de> In-Reply-To: <20100707145508.A42312A2B9@ochil.suse.de> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: linux-hotplug@vger.kernel.org Customers request connection (channel) and drive bay identifier to be part of the symlink name. On 07/07/2010 04:55 PM, Hannes Reinecke wrote: > > SAS devices should be referenced by the SAS address of the target; > on the initiator side we assume an identity mapping between SAS > addresses and PCI devnumber. > SATA devices have an identity mapping between SATA links and > linux scsi_host structures, so we can map the host number onto > the SATA link. > For this to work the LUN numbering needs to be updated, too, > as SATA devices do not have the concept of a LUN, whereas normal > SCSI devices have. > > Signed-off-by: Hannes Reinecke > > diff --git a/extras/path_id/path_id.c b/extras/path_id/path_id.c > index dcee378..1b6c363 100644 > --- a/extras/path_id/path_id.c > +++ b/extras/path_id/path_id.c > @@ -97,7 +97,6 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, > struct udev_device *targetdev; > struct udev_device *fcdev = NULL; > const char *port; > - unsigned int lun; > > targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); > if (targetdev = NULL) > @@ -112,8 +111,7 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, > goto out; > } > > - lun = strtoul(udev_device_get_sysnum(parent), NULL, 10); > - path_prepend(path, "fc-%s:0x%04x%04x00000000", port, lun& 0xffff, (lun>> 16)& 0xffff); > + path_prepend(path, "fc-%s", port); > out: > udev_device_unref(fcdev); > return parent; > @@ -121,7 +119,34 @@ out: > > static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **path) > { > - return NULL; > + struct udev *udev = udev_device_get_udev(parent); > + struct udev_device *end_dev = NULL; > + struct udev_device *sas_dev; > + const char *end_dev_wwn; > + > + /* Find end device */ > + end_dev = parent; > + while (1) { > + end_dev = udev_device_get_parent(end_dev); > + if (end_dev = NULL) > + return NULL; > + if (!strncmp(udev_device_get_sysname(end_dev), "end_device", 10)) > + break; > + } > + if (end_dev = NULL) > + return NULL; > + > + /* find sas end device */ > + sas_dev = udev_device_new_from_subsystem_sysname(udev, "sas_device", udev_device_get_sysname(end_dev)); > + if (sas_dev = NULL) > + return NULL; > + > + end_dev_wwn = udev_device_get_sysattr_value(sas_dev, "sas_address"); > + > + path_prepend(path, "sas-%s", end_dev_wwn); > + > + udev_device_unref(sas_dev); > + return end_dev; > } > > static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **path) > @@ -174,7 +199,7 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char ** > goto out; > } > > - path_prepend(path, "ip-%s:%s-iscsi-%s-lun-%s", addr, port, target, udev_device_get_sysnum(parent)); > + path_prepend(path, "ip-%s:%s-iscsi-%s", addr, port, target); > out: > udev_device_unref(sessiondev); > udev_device_unref(conndev); > @@ -183,23 +208,34 @@ out: > > static struct udev_device *handle_scsi_default(struct udev_device *parent, char **path) > { > + struct udev *udev = udev_device_get_udev(parent); > struct udev_device *hostdev; > - int host, bus, target, lun; > - const char *name; > + int host, bus, target; > + const char *name, *hba, *hostpath; > char *base; > char *pos; > + char *type = "scsi"; > DIR *dir; > struct dirent *dent; > - int basenum; > - > - hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host"); > - if (hostdev = NULL) > - return NULL; > + int basenum, hostnum = 0; > > name = udev_device_get_sysname(parent); > - if (sscanf(name, "%d:%d:%d:%d",&host,&bus,&target,&lun) != 4) > + if (sscanf(name, "target%d:%d:%d",&host,&bus,&target) != 3) > return NULL; > > + parent = udev_device_get_parent(parent); > + /* Check for libata hosts */ > + hostdev = udev_device_new_from_subsystem_sysname(udev, "scsi_host", udev_device_get_sysname(parent)); > + if (hostdev = NULL) > + return NULL; > + hba = udev_device_get_sysattr_value(hostdev, "proc_name"); > + if (hba&& (!strncmp(hba, "sata", 4) || !strcmp(hba, "ahci"))) > + type = "sata"; > + if (hba&& (!strncmp(hba, "pata", 4) || !strncmp(hba, "ata", 3))) > + type = "ata"; > + udev_device_unref(hostdev); > + /* Reset to original host path */ > + hostdev = parent; > /* rebase host offset to get the local relative number */ > basenum = -1; > base = strdup(udev_device_get_syspath(hostdev)); > @@ -227,6 +263,7 @@ static struct udev_device *handle_scsi_default(struct udev_device *parent, char > if (strncmp(dent->d_name, "host", 4) != 0) > continue; > i = strtoul(&dent->d_name[4],&rest, 10); > + hostnum++; > if (rest[0] != '\0') > continue; > if (basenum = -1 || i< basenum) > @@ -239,20 +276,54 @@ static struct udev_device *handle_scsi_default(struct udev_device *parent, char > } > host -= basenum; > > - path_prepend(path, "scsi-%u:%u:%u:%u", host, bus, target, lun); > + if (!strcmp(type, "scsi")) > + path_prepend(path, "scsi-%u:%u:%u", host, bus, target); > + else > + path_prepend(path, "%s-%u", type, host); > out: > free(base); > return hostdev; > } > > +static int scsi_is_sata(const char *name) > +{ > + char syspath[UTIL_PATH_SIZE]; > + struct stat stbuf; > + > + strcpy(syspath, name); > + strcat(syspath, "/unload_heads"); > + > + return (stat(syspath,&stbuf)< 0) ? 0 : 1; > +} > + > static struct udev_device *handle_scsi(struct udev_device *parent, char **path) > { > + struct udev *udev = udev_device_get_udev(parent); > const char *devtype; > const char *name; > const char *id; > > devtype = udev_device_get_devtype(parent); > - if (devtype = NULL || strcmp(devtype, "scsi_device") != 0) > + if (devtype = NULL) > + return parent; > + > + /* lousy scsi sysfs does not have a "subsystem" for the transport */ > + name = udev_device_get_syspath(parent); > + > + if (strcmp(devtype, "scsi_device") = 0) { > + if (!scsi_is_sata(name)) { > + unsigned int host, bus, target, lun; > + > + if (sscanf(udev_device_get_sysname(parent), > + "%d:%d:%d:%d",&host,&bus,&target,&lun) != 4) > + return NULL; > + path_prepend(path, "lun-0x%04x%04x00000000", > + lun& 0xffff, (lun>> 16)& 0xffff); > + } > + return parent; > + } > + > + if (strcmp(devtype, "scsi_host") = 0) > return parent; > > /* firewire */ > @@ -263,9 +334,6 @@ static struct udev_device *handle_scsi(struct udev_device *parent, char **path) > goto out; > } > > - /* lousy scsi sysfs does not have a "subsystem" for the transport */ > - name = udev_device_get_syspath(parent); > - > if (strstr(name, "/rport-") != NULL) { > parent = handle_scsi_fibre_channel(parent, path); > goto out; > -- > To unsubscribe from this list: send the line "unsubscribe linux-hotplug" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html