diff options
author | Hannes Reinecke <hare@suse.de> | 2016-02-19 09:16:59 +0100 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2016-02-23 21:27:02 -0500 |
commit | f2ecf13a248c828b4818056b65f18776a2ebd32b (patch) | |
tree | 21e504eb26bd59d200bbf5ab13e6df498e21e71f /drivers/scsi/device_handler/scsi_dh_alua.c | |
parent | d42ae5f338946928db7c7af23c6bdd7969a43487 (diff) | |
download | linux-f2ecf13a248c828b4818056b65f18776a2ebd32b.tar.bz2 |
scsi_dh_alua: separate out alua_stpg()
Separate out SET TARGET PORT GROUP functionality into a separate
function alua_stpg().
Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/device_handler/scsi_dh_alua.c')
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_alua.c | 95 |
1 files changed, 61 insertions, 34 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index df71e8523add..136bc7665b11 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -579,6 +579,65 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_ } /* + * alua_stpg - Issue a SET TARGET PORT GROUP command + * + * Issue a SET TARGET PORT GROUP command and evaluate the + * response. Returns SCSI_DH_RETRY if the target port group + * state is found to be in 'transitioning'. + * If SCSI_DH_OK is returned the passed-in 'fn' function + * this function will take care of executing 'fn'. + * Otherwise 'fn' should be executed by the caller with the + * returned error code. + */ +static unsigned alua_stpg(struct scsi_device *sdev, struct alua_dh_data *h, + activate_complete fn, void *data) +{ + int err = SCSI_DH_OK; + int stpg = 0; + + if (!(h->tpgs & TPGS_MODE_EXPLICIT)) + /* Only implicit ALUA supported */ + goto out; + + switch (h->state) { + case TPGS_STATE_NONOPTIMIZED: + stpg = 1; + if ((h->flags & ALUA_OPTIMIZE_STPG) && + !h->pref && + (h->tpgs & TPGS_MODE_IMPLICIT)) + stpg = 0; + break; + case TPGS_STATE_STANDBY: + case TPGS_STATE_UNAVAILABLE: + stpg = 1; + break; + case TPGS_STATE_OFFLINE: + err = SCSI_DH_IO; + break; + case TPGS_STATE_TRANSITIONING: + err = SCSI_DH_RETRY; + break; + default: + break; + } + + if (stpg) { + h->callback_fn = fn; + h->callback_data = data; + err = submit_stpg(h); + if (err != SCSI_DH_OK) + h->callback_fn = h->callback_data = NULL; + else + fn = NULL; + } +out: + if (fn) + fn(data, err); + + return err; +} + +/* * alua_initialize - Initialize ALUA state * @sdev: the device to be initialized * @@ -655,7 +714,6 @@ static int alua_activate(struct scsi_device *sdev, { struct alua_dh_data *h = sdev->handler_data; int err = SCSI_DH_OK; - int stpg = 0; err = alua_rtpg(sdev, h, 1); if (err != SCSI_DH_OK) @@ -664,41 +722,10 @@ static int alua_activate(struct scsi_device *sdev, if (optimize_stpg) h->flags |= ALUA_OPTIMIZE_STPG; - if (h->tpgs & TPGS_MODE_EXPLICIT) { - switch (h->state) { - case TPGS_STATE_NONOPTIMIZED: - stpg = 1; - if ((h->flags & ALUA_OPTIMIZE_STPG) && - (!h->pref) && - (h->tpgs & TPGS_MODE_IMPLICIT)) - stpg = 0; - break; - case TPGS_STATE_STANDBY: - case TPGS_STATE_UNAVAILABLE: - stpg = 1; - break; - case TPGS_STATE_OFFLINE: - err = SCSI_DH_IO; - break; - case TPGS_STATE_TRANSITIONING: - err = SCSI_DH_RETRY; - break; - default: - break; - } - } - - if (stpg) { - h->callback_fn = fn; - h->callback_data = data; - err = submit_stpg(h); - if (err == SCSI_DH_OK) - return 0; - h->callback_fn = h->callback_data = NULL; - } + err = alua_stpg(sdev, h, fn, data); out: - if (fn) + if (err != SCSI_DH_OK && fn) fn(data, err); return 0; } |