Provide callbacks for .is_disabled, .is_optimized, and .available_path.

These all use scsi_device.sdev_state and scsi_device.access_state.

Member scsi_device.access_state will be driven by ALUA. Currently
only device handlers support this, and in future we will have core
SCSI support for implicit ALUA (not relying on device handlers).

Signed-off-by: John Garry <[email protected]>
---
 drivers/scsi/scsi_multipath.c | 46 +++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/scsi/scsi_multipath.c b/drivers/scsi/scsi_multipath.c
index 0dcbf12217165..a3bf95e2a18eb 100644
--- a/drivers/scsi/scsi_multipath.c
+++ b/drivers/scsi/scsi_multipath.c
@@ -308,7 +308,53 @@ static enum mpath_iopolicy_e 
scsi_mpath_get_iopolicy(struct mpath_head *mpath_he
        return mpath_read_iopolicy(&scsi_mpath_head->iopolicy);
 }
 
+static bool scsi_mpath_is_disabled(struct mpath_device *mpath_device)
+{
+       struct scsi_mpath_device *scsi_mpath_dev =
+                               to_scsi_mpath_device(mpath_device);
+       struct scsi_device *sdev = scsi_mpath_dev->sdev;
+       unsigned char access_state = READ_ONCE(sdev->access_state);
+
+       if (sdev->sdev_state != SDEV_RUNNING)
+               return true;
+
+       if (access_state == SCSI_ACCESS_STATE_OPTIMAL ||
+           access_state == SCSI_ACCESS_STATE_ACTIVE)
+               return false;
+
+       return true;
+}
+
+static bool scsi_mpath_is_optimized(struct mpath_device *mpath_device)
+{
+       struct scsi_mpath_device *scsi_mpath_dev =
+                               to_scsi_mpath_device(mpath_device);
+       struct scsi_device *sdev = scsi_mpath_dev->sdev;
+
+       if (sdev->sdev_state != SDEV_RUNNING)
+               return false;
+
+       return READ_ONCE(sdev->access_state) == SCSI_ACCESS_STATE_OPTIMAL;
+}
+
+static bool scsi_mpath_available_path(struct mpath_device *mpath_device)
+{
+       struct scsi_mpath_device *scsi_mpath_dev =
+                               to_scsi_mpath_device(mpath_device);
+       struct scsi_device *sdev = scsi_mpath_dev->sdev;
+       enum scsi_device_state sdev_state = sdev->sdev_state;
+
+       if (sdev_state == SDEV_RUNNING || sdev_state == SDEV_QUIESCE ||
+           sdev_state == SDEV_BLOCK || sdev_state == SDEV_CREATED_BLOCK)
+               return true;
+
+       return false;
+}
+
 struct mpath_head_template smpdt = {
+       .is_disabled = scsi_mpath_is_disabled,
+       .is_optimized = scsi_mpath_is_optimized,
+       .available_path = scsi_mpath_available_path,
        .get_iopolicy = scsi_mpath_get_iopolicy,
        .clone_bio = scsi_mpath_clone_bio,
 };
-- 
2.43.5


Reply via email to