Set recovery_tmo for iSCSI devices
authorHannes Reinecke <hare@suse.de>
Wed, 16 Jan 2013 12:14:14 +0000 (13:14 +0100)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Wed, 16 Jan 2013 20:57:26 +0000 (21:57 +0100)
iSCSI has a 'recovery_tmo' value, which works similar to the
'fast_io_fail' mechanism on FibreChannel.
So we should be setting it from multipath, too.

Signed-off-by: Hannes Reinecke <hare@suse.de>
libmultipath/discovery.c

index b6bce22..a099996 100644 (file)
@@ -254,19 +254,22 @@ sysfs_get_tgt_nodename (struct path *pp, char * node)
        targetid = NULL;
        while (parent) {
                targetid = udev_device_get_sysname(parent);
-               if (!strncmp(targetid , "session", 6))
+               if (targetid && sscanf(targetid , "session%d", &rport_id) == 1)
                        break;
                parent = udev_device_get_parent(parent);
                targetid = NULL;
+               rport_id = -1;
        }
-       if (parent) {
-               tgtdev = udev_device_new_from_subsystem_sysname(conf->udev, "iscsi_session", targetid);
+       if (parent && targetid) {
+               tgtdev = udev_device_new_from_subsystem_sysname(conf->udev,
+                               "iscsi_session", targetid);
                if (tgtdev) {
                        const char *value;
 
                        value = udev_device_get_sysattr_value(tgtdev, "targetname");
                        if (value) {
                                pp->sg_id.proto_id = SCSI_PROTOCOL_ISCSI;
+                               pp->sg_id.transport_id = rport_id;
                                strncpy(node, value, NODE_NAME_SIZE);
                                udev_device_unref(tgtdev);
                                return 0;
@@ -302,10 +305,6 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
        char value[11];
        char rport_id[32];
 
-       if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP) {
-               condlog(3, "%s: Not a FCP device", pp->dev);
-               return;
-       }
        sprintf(rport_id, "rport-%d:%d-%d",
                pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
        rport_dev = udev_device_new_from_subsystem_sysname(conf->udev,
@@ -351,6 +350,47 @@ out:
        udev_device_unref(rport_dev);
 }
 
+static void
+sysfs_set_session_tmo(struct multipath *mpp, struct path *pp)
+{
+       struct udev_device *session_dev = NULL;
+       char session_id[64];
+       char value[11];
+
+       sprintf(session_id, "session%d", pp->sg_id.transport_id);
+       session_dev = udev_device_new_from_subsystem_sysname(conf->udev,
+                               "iscsi_session", session_id);
+       if (!session_dev) {
+               condlog(1, "%s: No iscsi session for '%s'", pp->dev,
+                       session_id);
+               return;
+       }
+       condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no,
+               pp->sg_id.channel, pp->sg_id.scsi_id, session_id);
+
+       if (mpp->dev_loss) {
+               condlog(3, "%s: ignoring dev_loss_tmo on iSCSI", pp->dev);
+       }
+       if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
+               if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF) {
+                       condlog(3, "%s: can't switch off fast_io_fail_tmo "
+                               "on iSCSI", pp->dev);
+               } else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO) {
+                       condlog(3, "%s: can't set fast_io_fail_tmo to '0'"
+                               "on iSCSI", pp->dev);
+               } else {
+                       snprintf(value, 11, "%u", mpp->fast_io_fail);
+                       if (sysfs_attr_set_value(session_dev, "recovery_tmo",
+                                                value, 11)) {
+                               condlog(3, "%s: Failed to set recovery_tmo, "
+                                       " error %d", pp->dev, errno);
+                       }
+               }
+       }
+       udev_device_unref(session_dev);
+       return;
+}
+
 int
 sysfs_set_scsi_tmo (struct multipath *mpp)
 {
@@ -382,7 +422,10 @@ sysfs_set_scsi_tmo (struct multipath *mpp)
                return 0;
 
        vector_foreach_slot(mpp->paths, pp, i) {
-               sysfs_set_rport_tmo(mpp, pp);
+               if (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP)
+                       sysfs_set_rport_tmo(mpp, pp);
+               if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI)
+                       sysfs_set_session_tmo(mpp, pp);
        }
        return 0;
 }