153 lines
3.8 KiB
Plaintext
153 lines
3.8 KiB
Plaintext
commit 08a140c02f9010f356e5b18dc7b7652cc15fc79d
|
|
Author: Hannes Reinecke <hare@suse.de>
|
|
Date: Fri Sep 26 15:31:07 2008 +0200
|
|
|
|
multipath: Check return value for get_inq()
|
|
|
|
Check the return value of get_inq() to correctly handle devices
|
|
with unconnected LUNs.
|
|
|
|
References: 419123
|
|
Signed-off-by: Hannes Reinecke <hare@suse.de>
|
|
|
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
|
index dd45e03..e1a67ac 100644
|
|
--- a/libmultipath/discovery.c
|
|
+++ b/libmultipath/discovery.c
|
|
@@ -275,7 +275,7 @@ devt2devname (char *devname, char *devt)
|
|
|
|
int
|
|
do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
|
|
- void *resp, int mx_resp_len, int noisy)
|
|
+ void *resp, int mx_resp_len)
|
|
{
|
|
unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
|
|
{ INQUIRY_CMD, 0, 0, 0, 0, 0 };
|
|
@@ -334,7 +334,7 @@ get_serial (char * str, int maxlen, int fd)
|
|
if (fd < 0)
|
|
return 1;
|
|
|
|
- if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) {
|
|
+ if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN)) {
|
|
len = buff[3];
|
|
if (len >= maxlen)
|
|
return 1;
|
|
@@ -348,26 +348,69 @@ get_serial (char * str, int maxlen, int fd)
|
|
}
|
|
|
|
static int
|
|
-get_inq (char * vendor, char * product, char * rev, int fd)
|
|
+get_inq (char * dev, char * vendor, char * product, char * rev, int fd)
|
|
{
|
|
- char buff[MX_ALLOC_LEN + 1] = {0};
|
|
+ unsigned char buff[MX_ALLOC_LEN + 1] = {0};
|
|
+ int len;
|
|
|
|
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';
|
|
- strchop(vendor);
|
|
- memcpy(product, buff + 16, 16);
|
|
- product[16] = '\0';
|
|
- strchop(product);
|
|
- memcpy(rev, buff + 32, 4);
|
|
- rev[4] = '\0';
|
|
- strchop(rev);
|
|
- return 0;
|
|
+ if (0 != do_inq(fd, 0, 0, 0, buff, MX_ALLOC_LEN))
|
|
+ return 1;
|
|
+
|
|
+ /* Check peripheral qualifier */
|
|
+ if ((buff[0] >> 5) != 0) {
|
|
+ int pqual = (buff[0] >> 5);
|
|
+ switch (pqual) {
|
|
+ case 1:
|
|
+ condlog(3, "%s: INQUIRY failed, LU not connected", dev);
|
|
+ break;
|
|
+ case 3:
|
|
+ condlog(3, "%s: INQUIRY failed, LU not supported", dev);
|
|
+ break;
|
|
+ default:
|
|
+ condlog(3, "%s: INQUIRY failed, Invalid PQ %x",
|
|
+ dev, pqual);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
}
|
|
- return 1;
|
|
+
|
|
+ len = buff[4] + 4;
|
|
+
|
|
+ if (len < 8) {
|
|
+ condlog(3, "%s: INQUIRY response too short (len %d)",
|
|
+ dev, len);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ len -= 8;
|
|
+ memset(vendor, 0x0, 8);
|
|
+ memcpy(vendor, buff + 8, len > 8 ? 8 : len);
|
|
+ vendor[8] = '\0';
|
|
+ strchop(vendor);
|
|
+ if (len <= 8)
|
|
+ return 0;
|
|
+
|
|
+ len -= 8;
|
|
+
|
|
+ memset(product, 0x0, 16);
|
|
+ memcpy(product, buff + 16, len > 16 ? 16 : len);
|
|
+ product[16] = '\0';
|
|
+ strchop(product);
|
|
+ if (len <= 16)
|
|
+ return 0;
|
|
+
|
|
+ len -= 16;
|
|
+
|
|
+ memset(rev, 0x0, 4);
|
|
+ memcpy(rev, buff + 32, 4);
|
|
+ rev[4] = '\0';
|
|
+ strchop(rev);
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
static int
|
|
@@ -549,13 +592,16 @@ sysfs_pathinfo(struct path * pp)
|
|
if (!strncmp(parent->kernel, "block",5))
|
|
parent = sysfs_device_get_parent(parent);
|
|
|
|
+ if (!strncmp(pp->dev,"cciss",5))
|
|
+ strcpy(parent->subsystem,"cciss");
|
|
+
|
|
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))
|
|
+ if (!strncmp(parent->subsystem,"cciss",5))
|
|
pp->bus = SYSFS_BUS_CCISS;
|
|
|
|
if (pp->bus == SYSFS_BUS_UNDEF)
|
|
@@ -587,8 +633,14 @@ scsi_ioctl_pathinfo (struct path * pp, int mask)
|
|
static int
|
|
cciss_ioctl_pathinfo (struct path * pp, int mask)
|
|
{
|
|
+ int ret;
|
|
+
|
|
if (mask & DI_SYSFS) {
|
|
- get_inq(pp->vendor_id, pp->product_id, pp->rev, pp->fd);
|
|
+ ret = get_inq(pp->dev, pp->vendor_id, pp->product_id,
|
|
+ pp->rev, pp->fd);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
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);
|