libmultipath: clariion checker: leave unsupported paths alone
authorMartin Wilck <mwilck@suse.com>
Fri, 2 Nov 2018 12:21:17 +0000 (13:21 +0100)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Wed, 14 Nov 2018 07:21:35 +0000 (08:21 +0100)
A checker shouldn't set the path state to PATH_DOWN if it fails
to obtain information about the path in the first place. Add logic
to the checker to distinguish a failed path from an unsupported path.

Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Martin Wilck <mwilck@suse.com>
libmultipath/checkers/emc_clariion.c

index f8e55b9..6fc8911 100644 (file)
 #define INQUIRY_CMD     0x12
 #define INQUIRY_CMDLEN  6
 #define HEAVY_CHECK_COUNT       10
+#define SCSI_COMMAND_TERMINATED        0x22
+#define SCSI_CHECK_CONDITION   0x2
+#define RECOVERED_ERROR                0x01
+#define ILLEGAL_REQUEST                0x05
+#define SG_ERR_DRIVER_SENSE    0x08
 
 /*
  * Mechanism to track CLARiiON inactive snapshot LUs.
@@ -130,7 +135,9 @@ int libcheck_check (struct checker * c)
                (struct emc_clariion_checker_path_context *)c->context;
        char wwnstr[33];
        int ret;
+       int retry_emc = 5;
 
+retry:
        memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
        memset(sense_buffer, 0, 128);
        memset(sb, 0, SENSE_BUFF_LEN);
@@ -145,13 +152,60 @@ int libcheck_check (struct checker * c)
        io_hdr.timeout = c->timeout * 1000;
        io_hdr.pack_id = 0;
        if (ioctl(c->fd, SG_IO, &io_hdr) < 0) {
+               if (errno == ENOTTY) {
+                       c->msgid = CHECKER_MSGID_UNSUPPORTED;
+                       return PATH_WILD;
+               }
                c->msgid = MSG_CLARIION_QUERY_FAILED;
                return PATH_DOWN;
        }
+
        if (io_hdr.info & SG_INFO_OK_MASK) {
+               switch (io_hdr.host_status) {
+               case DID_BUS_BUSY:
+               case DID_ERROR:
+               case DID_SOFT_ERROR:
+               case DID_TRANSPORT_DISRUPTED:
+                       /* Transport error, retry */
+                       if (--retry_emc)
+                               goto retry;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (SCSI_CHECK_CONDITION == io_hdr.status ||
+           SCSI_COMMAND_TERMINATED == io_hdr.status ||
+           SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status)) {
+               if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
+                       unsigned char *sbp = io_hdr.sbp;
+                       int sense_key;
+
+                       if (sbp[0] & 0x2)
+                               sense_key = sbp[1] & 0xf;
+                       else
+                               sense_key = sbp[2] & 0xf;
+
+                       if (sense_key == ILLEGAL_REQUEST) {
+                               c->msgid = CHECKER_MSGID_UNSUPPORTED;
+                               return PATH_WILD;
+                       } else if (sense_key != RECOVERED_ERROR) {
+                               condlog(1, "emc_clariion_checker: INQUIRY failed with sense key %02x",
+                                       sense_key);
+                               c->msgid = MSG_CLARIION_QUERY_ERROR;
+                               return PATH_DOWN;
+                       }
+               }
+       }
+
+       if (io_hdr.info & SG_INFO_OK_MASK) {
+               condlog(1, "emc_clariion_checker: INQUIRY failed without sense, status %02x",
+                       io_hdr.status);
                c->msgid = MSG_CLARIION_QUERY_ERROR;
                return PATH_DOWN;
        }
+
        if (/* Verify the code page - right page & revision */
            sense_buffer[1] != 0xc0 || sense_buffer[9] != 0x00) {
                c->msgid = MSG_CLARIION_UNIT_REPORT;