To allow the initiator know of any ALUA configuration changes, issue a
periodic TUR.

multipathd does something similar for dm-multipath in terms of issuing
a periodic read per path.

The purpose of the TUR is that the target can update UA info in the TUR
response and the INI can handle it, but currently we don't for SCSI
multipath.

Signed-off-by: John Garry <[email protected]>
---
 drivers/scsi/scsi_multipath.c | 36 +++++++++++++++++++++++++++++++++++
 include/scsi/scsi_multipath.h |  1 +
 2 files changed, 37 insertions(+)

diff --git a/drivers/scsi/scsi_multipath.c b/drivers/scsi/scsi_multipath.c
index 0c34b1151f5bf..2b916c7af4bd7 100644
--- a/drivers/scsi/scsi_multipath.c
+++ b/drivers/scsi/scsi_multipath.c
@@ -4,6 +4,7 @@
  *
  */
 
+#include <linux/kthread.h>
 #include <scsi/scsi_alua.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_driver.h>
@@ -124,6 +125,7 @@ static void scsi_mpath_head_release(struct device *dev)
                container_of(dev, struct scsi_mpath_head, dev);
        struct mpath_head *mpath_head = scsi_mpath_head->mpath_head;
 
+       WARN_ON_ONCE(kthread_stop(scsi_mpath_head->kua));
        scsi_mpath_delete_head(scsi_mpath_head);
        bioset_exit(&scsi_mpath_head->bio_pool);
        ida_free(&scsi_multipath_dev_ida, scsi_mpath_head->index);
@@ -514,6 +516,29 @@ struct mpath_head_template smpdt_pr = {
        .device_groups = mpath_device_groups,
 };
 
+static void scsi_mpath_cb_ua_thread(struct mpath_device *mpath_device)
+{
+       struct scsi_mpath_device *scsi_mpath_dev =
+                       to_scsi_mpath_device(mpath_device);
+
+       if (alua_tur(scsi_mpath_dev->sdev))
+               sdev_printk(KERN_NOTICE, scsi_mpath_dev->sdev,
+                           "%s: No target port descriptors found\n",
+                           __func__);
+}
+
+static int scsi_mpath_ua_thread(void *data)
+{
+       struct scsi_mpath_head *scsi_mpath_head = data;
+
+       while (!kthread_should_stop()) {
+               mpath_call_for_all_devices(scsi_mpath_head->mpath_head,
+                       scsi_mpath_cb_ua_thread);
+               msleep(5000);
+       }
+       return 0;
+}
+
 static struct scsi_mpath_head *scsi_mpath_alloc_head(void)
 {
        struct scsi_mpath_head *scsi_mpath_head;
@@ -548,6 +573,17 @@ static struct scsi_mpath_head *scsi_mpath_alloc_head(void)
                goto out_free_ida;
        }
 
+       scsi_mpath_head->kua = kthread_create(scsi_mpath_ua_thread,
+                       scsi_mpath_head, "scsi-multipath-kua-%d",
+                       scsi_mpath_head->index);
+       if (IS_ERR(scsi_mpath_head->kua)) {
+               put_device(&scsi_mpath_head->dev);
+               goto out_free_ida;
+       }
+
+       set_user_nice(scsi_mpath_head->kua, 10);
+       wake_up_process(scsi_mpath_head->kua);
+
        return scsi_mpath_head;
 
 out_free_ida:
diff --git a/include/scsi/scsi_multipath.h b/include/scsi/scsi_multipath.h
index 7c7ee2fb7def7..d30f2c41e17de 100644
--- a/include/scsi/scsi_multipath.h
+++ b/include/scsi/scsi_multipath.h
@@ -30,6 +30,7 @@ struct scsi_mpath_head {
        struct mpath_head       *mpath_head;
        struct device           dev;
        int                     index;
+       struct task_struct      *kua;
 };
 
 struct scsi_mpath_device {
-- 
2.43.5


Reply via email to