Switch to use core scsi ALUA support. We still need to drive the state machine for explicit ALUA.
Signed-off-by: John Garry <[email protected]> --- drivers/scsi/device_handler/scsi_dh_alua.c | 580 +-------------------- 1 file changed, 21 insertions(+), 559 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 067021fffc16f..4d53fab85a7ed 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -10,6 +10,7 @@ #include <linux/module.h> #include <linux/unaligned.h> #include <scsi/scsi.h> +#include <scsi/scsi_alua.h> #include <scsi/scsi_proto.h> #include <scsi/scsi_dbg.h> #include <scsi/scsi_eh.h> @@ -44,7 +45,6 @@ /* device handler flags */ #define ALUA_OPTIMIZE_STPG 0x01 -#define ALUA_RTPG_EXT_HDR_UNSUPP 0x02 /* State machine flags */ #define ALUA_PG_RUN_RTPG 0x10 #define ALUA_PG_RUN_STPG 0x20 @@ -65,14 +65,6 @@ struct alua_dh_data { unsigned flags; /* used for optimizing STPG */ spinlock_t lock; - /* alua stuff */ - int state; - int pref; - int valid_states; - int tpgs; - unsigned char transition_tmo; - unsigned long expiry; - unsigned long interval; struct delayed_work rtpg_work; struct list_head rtpg_list; }; @@ -91,121 +83,6 @@ static bool alua_rtpg_queue(struct scsi_device *sdev, struct alua_queue_data *qdata, bool force); static void alua_check(struct scsi_device *sdev, bool force); -/* - * submit_rtpg - Issue a REPORT TARGET GROUP STATES command - * @sdev: sdev the command should be sent to - */ -static int submit_rtpg(struct scsi_device *sdev, unsigned char *buff, - int bufflen, struct scsi_sense_hdr *sshdr, int flags) -{ - u8 cdb[MAX_COMMAND_SIZE]; - blk_opf_t opf = REQ_OP_DRV_IN | REQ_FAILFAST_DEV | - REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER; - const struct scsi_exec_args exec_args = { - .sshdr = sshdr, - }; - - /* Prepare the command. */ - memset(cdb, 0x0, MAX_COMMAND_SIZE); - cdb[0] = MAINTENANCE_IN; - if (!(flags & ALUA_RTPG_EXT_HDR_UNSUPP)) - cdb[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT; - else - cdb[1] = MI_REPORT_TARGET_PGS; - put_unaligned_be32(bufflen, &cdb[6]); - - return scsi_execute_cmd(sdev, cdb, opf, buff, bufflen, - ALUA_FAILOVER_TIMEOUT * HZ, - ALUA_FAILOVER_RETRIES, &exec_args); -} - -/* - * submit_stpg - Issue a SET TARGET PORT GROUP command - * - * Currently we're only setting the current target port group state - * to 'active/optimized' and let the array firmware figure out - * the states of the remaining groups. - */ -static int submit_stpg(struct scsi_device *sdev, int group_id, - struct scsi_sense_hdr *sshdr) -{ - u8 cdb[MAX_COMMAND_SIZE]; - unsigned char stpg_data[8]; - int stpg_len = 8; - blk_opf_t opf = REQ_OP_DRV_OUT | REQ_FAILFAST_DEV | - REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER; - const struct scsi_exec_args exec_args = { - .sshdr = sshdr, - }; - - /* Prepare the data buffer */ - memset(stpg_data, 0, stpg_len); - stpg_data[4] = SCSI_ACCESS_STATE_OPTIMAL; - put_unaligned_be16(group_id, &stpg_data[6]); - - /* Prepare the command. */ - memset(cdb, 0x0, MAX_COMMAND_SIZE); - cdb[0] = MAINTENANCE_OUT; - cdb[1] = MO_SET_TARGET_PGS; - put_unaligned_be32(stpg_len, &cdb[6]); - - return scsi_execute_cmd(sdev, cdb, opf, stpg_data, - stpg_len, ALUA_FAILOVER_TIMEOUT * HZ, - ALUA_FAILOVER_RETRIES, &exec_args); -} - -/* - * alua_check_tpgs - Evaluate TPGS setting - * @sdev: device to be checked - * - * Examine the TPGS setting of the sdev to find out if ALUA - * is supported. - */ -static int alua_check_tpgs(struct scsi_device *sdev) -{ - int tpgs = TPGS_MODE_NONE; - - /* - * ALUA support for non-disk devices is fraught with - * difficulties, so disable it for now. - */ - if (sdev->type != TYPE_DISK) { - sdev_printk(KERN_INFO, sdev, - "%s: disable for non-disk devices\n", - ALUA_DH_NAME); - return tpgs; - } - - tpgs = scsi_device_tpgs(sdev); - switch (tpgs) { - case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT: - sdev_printk(KERN_INFO, sdev, - "%s: supports implicit and explicit TPGS\n", - ALUA_DH_NAME); - break; - case TPGS_MODE_EXPLICIT: - sdev_printk(KERN_INFO, sdev, "%s: supports explicit TPGS\n", - ALUA_DH_NAME); - break; - case TPGS_MODE_IMPLICIT: - sdev_printk(KERN_INFO, sdev, "%s: supports implicit TPGS\n", - ALUA_DH_NAME); - break; - case TPGS_MODE_NONE: - sdev_printk(KERN_INFO, sdev, "%s: not supported\n", - ALUA_DH_NAME); - break; - default: - sdev_printk(KERN_INFO, sdev, - "%s: unsupported TPGS setting %d\n", - ALUA_DH_NAME, tpgs); - tpgs = TPGS_MODE_NONE; - break; - } - - return tpgs; -} - /* * alua_check_vpd - Evaluate INQUIRY vpd page 0x83 * @sdev: device to be checked @@ -216,56 +93,11 @@ static int alua_check_tpgs(struct scsi_device *sdev) static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h, int tpgs) { - int rel_port = -1; - - h->group_id = scsi_vpd_tpg_id(sdev, &rel_port); - if (h->group_id < 0) { - /* - * Internal error; TPGS supported but required - * VPD identification descriptors not present. - * Disable ALUA support - */ - sdev_printk(KERN_INFO, sdev, - "%s: No target port descriptors found\n", - ALUA_DH_NAME); - return SCSI_DH_DEV_UNSUPP; - } - h->tpgs = tpgs; - alua_rtpg_queue(sdev, NULL, true); return SCSI_DH_OK; } -static char print_alua_state(unsigned char state) -{ - switch (state) { - case SCSI_ACCESS_STATE_OPTIMAL: - return 'A'; - case SCSI_ACCESS_STATE_ACTIVE: - return 'N'; - case SCSI_ACCESS_STATE_STANDBY: - return 'S'; - case SCSI_ACCESS_STATE_UNAVAILABLE: - return 'U'; - case SCSI_ACCESS_STATE_LBA: - return 'L'; - case SCSI_ACCESS_STATE_OFFLINE: - return 'O'; - case SCSI_ACCESS_STATE_TRANSITIONING: - return 'T'; - default: - return 'X'; - } -} - -static void alua_handle_state_transition(struct scsi_device *sdev) -{ - struct alua_dh_data *h = sdev->handler_data; - - h->state = SCSI_ACCESS_STATE_TRANSITIONING; -} - static enum scsi_disposition alua_check_sense(struct scsi_device *sdev, struct scsi_sense_hdr *sense_hdr) { @@ -275,7 +107,7 @@ static enum scsi_disposition alua_check_sense(struct scsi_device *sdev, /* * LUN Not Accessible - ALUA state transition */ - alua_handle_state_transition(sdev); + scsi_alua_handle_state_transition(sdev); return NEEDS_RETRY; } break; @@ -284,7 +116,7 @@ static enum scsi_disposition alua_check_sense(struct scsi_device *sdev, /* * LUN Not Accessible - ALUA state transition */ - alua_handle_state_transition(sdev); + scsi_alua_handle_state_transition(sdev); return NEEDS_RETRY; } if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00) { @@ -338,329 +170,6 @@ static enum scsi_disposition alua_check_sense(struct scsi_device *sdev, return SCSI_RETURN_NOT_HANDLED; } -/* - * alua_tur - Send a TEST UNIT READY - * @sdev: device to which the TEST UNIT READY command should be send - * - * Send a TEST UNIT READY to @sdev to figure out the device state - * Returns SCSI_DH_RETRY if the sense code is NOT READY/ALUA TRANSITIONING, - * SCSI_DH_OK if no error occurred, and SCSI_DH_IO otherwise. - */ -static int alua_tur(struct scsi_device *sdev) -{ - struct scsi_sense_hdr sense_hdr; - int retval; - - retval = scsi_test_unit_ready(sdev, ALUA_FAILOVER_TIMEOUT * HZ, - ALUA_FAILOVER_RETRIES, &sense_hdr); - if ((sense_hdr.sense_key == NOT_READY || - sense_hdr.sense_key == UNIT_ATTENTION) && - sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a) - return SCSI_DH_RETRY; - else if (retval) - return SCSI_DH_IO; - else - return SCSI_DH_OK; -} - -/* - * alua_rtpg - Evaluate REPORT TARGET GROUP STATES - * @sdev: the device to be evaluated. - * - * Evaluate the Target Port Group State. - * Returns SCSI_DH_DEV_OFFLINED if the path is - * found to be unusable. - */ -static int alua_rtpg(struct scsi_device *sdev) -{ - struct scsi_sense_hdr sense_hdr; - struct alua_dh_data *h = sdev->handler_data; - int len, k, off, bufflen = ALUA_RTPG_SIZE; - int group_id_old, state_old, pref_old, valid_states_old; - unsigned char *desc, *buff; - unsigned err; - int retval; - unsigned int tpg_desc_tbl_off; - unsigned char orig_transition_tmo; - unsigned long flags; - bool transitioning_sense = false; - int rel_port, group_id = scsi_vpd_tpg_id(sdev, &rel_port); - - if (group_id < 0) { - /* - * Internal error; TPGS supported but required - * VPD identification descriptors not present. - * Disable ALUA support - */ - sdev_printk(KERN_INFO, sdev, - "%s: No target port descriptors found\n", - ALUA_DH_NAME); - return SCSI_DH_DEV_UNSUPP; - } - - group_id_old = h->group_id; - state_old = h->state; - pref_old = h->pref; - valid_states_old = h->valid_states; - - if (!h->expiry) { - unsigned long transition_tmo = ALUA_FAILOVER_TIMEOUT * HZ; - - if (h->transition_tmo) - transition_tmo = h->transition_tmo * HZ; - - h->expiry = round_jiffies_up(jiffies + transition_tmo); - } - - buff = kzalloc(bufflen, GFP_KERNEL); - if (!buff) - return SCSI_DH_DEV_TEMP_BUSY; - - retry: - err = 0; - retval = submit_rtpg(sdev, buff, bufflen, &sense_hdr, h->flags); - - if (retval) { - /* - * Some (broken) implementations have a habit of returning - * an error during things like firmware update etc. - * But if the target only supports active/optimized there's - * not much we can do; it's not that we can switch paths - * or anything. - * So ignore any errors to avoid spurious failures during - * path failover. - */ - if ((h->valid_states & ~TPGS_SUPPORT_OPTIMIZED) == 0) { - sdev_printk(KERN_INFO, sdev, - "%s: ignoring rtpg result %d\n", - ALUA_DH_NAME, retval); - kfree(buff); - return SCSI_DH_OK; - } - if (retval < 0 || !scsi_sense_valid(&sense_hdr)) { - sdev_printk(KERN_INFO, sdev, - "%s: rtpg failed, result %d\n", - ALUA_DH_NAME, retval); - kfree(buff); - if (retval < 0) - return SCSI_DH_DEV_TEMP_BUSY; - if (host_byte(retval) == DID_NO_CONNECT) - return SCSI_DH_RES_TEMP_UNAVAIL; - return SCSI_DH_IO; - } - - /* - * submit_rtpg() has failed on existing arrays - * when requesting extended header info, and - * the array doesn't support extended headers, - * even though it shouldn't according to T10. - * The retry without rtpg_ext_hdr_req set - * handles this. - * Note: some arrays return a sense key of ILLEGAL_REQUEST - * with ASC 00h if they don't support the extended header. - */ - if (!(h->flags & ALUA_RTPG_EXT_HDR_UNSUPP) && - sense_hdr.sense_key == ILLEGAL_REQUEST) { - h->flags |= ALUA_RTPG_EXT_HDR_UNSUPP; - goto retry; - } - /* - * If the array returns with 'ALUA state transition' - * sense code here it cannot return RTPG data during - * transition. So set the state to 'transitioning' directly. - */ - if (sense_hdr.sense_key == NOT_READY && - sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a) { - transitioning_sense = true; - goto skip_rtpg; - } - /* - * Retry on any other UNIT ATTENTION occurred. - */ - if (sense_hdr.sense_key == UNIT_ATTENTION) - err = SCSI_DH_RETRY; - if (err == SCSI_DH_RETRY && - h->expiry != 0 && time_before(jiffies, h->expiry)) { - sdev_printk(KERN_ERR, sdev, "%s: rtpg retry\n", - ALUA_DH_NAME); - scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr); - kfree(buff); - return err; - } - sdev_printk(KERN_ERR, sdev, "%s: rtpg failed\n", - ALUA_DH_NAME); - scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr); - kfree(buff); - h->expiry = 0; - return SCSI_DH_IO; - } - - len = get_unaligned_be32(&buff[0]) + 4; - - if (len > bufflen) { - /* Resubmit with the correct length */ - kfree(buff); - bufflen = len; - buff = kmalloc(bufflen, GFP_KERNEL); - if (!buff) { - sdev_printk(KERN_WARNING, sdev, - "%s: kmalloc buffer failed\n",__func__); - /* Temporary failure, bypass */ - h->expiry = 0; - return SCSI_DH_DEV_TEMP_BUSY; - } - goto retry; - } - - orig_transition_tmo = h->transition_tmo; - if ((buff[4] & RTPG_FMT_MASK) == RTPG_FMT_EXT_HDR && buff[5] != 0) - h->transition_tmo = buff[5]; - else - h->transition_tmo = ALUA_FAILOVER_TIMEOUT; - - if (orig_transition_tmo != h->transition_tmo) { - sdev_printk(KERN_INFO, sdev, - "%s: transition timeout set to %d seconds\n", - ALUA_DH_NAME, h->transition_tmo); - h->expiry = jiffies + h->transition_tmo * HZ; - } - - if ((buff[4] & RTPG_FMT_MASK) == RTPG_FMT_EXT_HDR) - tpg_desc_tbl_off = 8; - else - tpg_desc_tbl_off = 4; - - for (k = tpg_desc_tbl_off, desc = buff + tpg_desc_tbl_off; - k < len; - k += off, desc += off) { - u16 group_id_desc = get_unaligned_be16(&desc[2]); - - spin_lock_irqsave(&h->lock, flags); - if (group_id_desc == group_id) { - h->group_id = group_id; - WRITE_ONCE(h->state, desc[0] & 0x0f); - h->pref = desc[0] >> 7; - WRITE_ONCE(sdev->access_state, desc[0]); - h->valid_states = desc[1]; - } - spin_unlock_irqrestore(&h->lock, flags); - off = 8 + (desc[7] * 4); - } - - skip_rtpg: - spin_lock_irqsave(&h->lock, flags); - if (transitioning_sense) - h->state = SCSI_ACCESS_STATE_TRANSITIONING; - - if (group_id_old != h->group_id || state_old != h->state || - pref_old != h->pref || valid_states_old != h->valid_states) - sdev_printk(KERN_INFO, sdev, - "%s: port group %02x state %c %s supports %c%c%c%c%c%c%c\n", - ALUA_DH_NAME, h->group_id, print_alua_state(h->state), - h->pref ? "preferred" : "non-preferred", - h->valid_states&TPGS_SUPPORT_TRANSITION?'T':'t', - h->valid_states&TPGS_SUPPORT_OFFLINE?'O':'o', - h->valid_states&TPGS_SUPPORT_LBA_DEPENDENT?'L':'l', - h->valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u', - h->valid_states&TPGS_SUPPORT_STANDBY?'S':'s', - h->valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n', - h->valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a'); - - switch (h->state) { - case SCSI_ACCESS_STATE_TRANSITIONING: - if (time_before(jiffies, h->expiry)) { - /* State transition, retry */ - h->interval = ALUA_RTPG_RETRY_DELAY; - err = SCSI_DH_RETRY; - } else { - struct alua_dh_data *h; - unsigned char access_state; - - /* Transitioning time exceeded, set port to standby */ - err = SCSI_DH_IO; - h->state = SCSI_ACCESS_STATE_STANDBY; - h->expiry = 0; - access_state = h->state & SCSI_ACCESS_STATE_MASK; - if (h->pref) - access_state |= SCSI_ACCESS_STATE_PREFERRED; - WRITE_ONCE(sdev->access_state, access_state); - } - break; - case SCSI_ACCESS_STATE_OFFLINE: - /* Path unusable */ - err = SCSI_DH_DEV_OFFLINED; - h->expiry = 0; - break; - default: - /* Useable path if active */ - err = SCSI_DH_OK; - h->expiry = 0; - break; - } - spin_unlock_irqrestore(&h->lock, flags); - kfree(buff); - return err; -} - -/* - * alua_stpg - Issue a SET TARGET PORT GROUP command - * - * Issue a SET TARGET PORT GROUP command and evaluate the - * response. Returns SCSI_DH_RETRY per default to trigger - * a re-evaluation of the target group state or SCSI_DH_OK - * if no further action needs to be taken. - */ -static unsigned alua_stpg(struct scsi_device *sdev) -{ - int retval; - struct scsi_sense_hdr sense_hdr; - struct alua_dh_data *h = sdev->handler_data; - - if (!(h->tpgs & TPGS_MODE_EXPLICIT)) { - /* Only implicit ALUA supported, retry */ - return SCSI_DH_RETRY; - } - switch (h->state) { - case SCSI_ACCESS_STATE_OPTIMAL: - return SCSI_DH_OK; - case SCSI_ACCESS_STATE_ACTIVE: - if ((h->flags & ALUA_OPTIMIZE_STPG) && - !h->pref && - (h->tpgs & TPGS_MODE_IMPLICIT)) - return SCSI_DH_OK; - break; - case SCSI_ACCESS_STATE_STANDBY: - case SCSI_ACCESS_STATE_UNAVAILABLE: - break; - case SCSI_ACCESS_STATE_OFFLINE: - return SCSI_DH_IO; - case SCSI_ACCESS_STATE_TRANSITIONING: - break; - default: - sdev_printk(KERN_INFO, sdev, - "%s: stpg failed, unhandled TPGS state %d", - ALUA_DH_NAME, h->state); - return SCSI_DH_NOSYS; - } - retval = submit_stpg(sdev, h->group_id, &sense_hdr); - - if (retval) { - if (retval < 0 || !scsi_sense_valid(&sense_hdr)) { - sdev_printk(KERN_INFO, sdev, - "%s: stpg failed, result %d", - ALUA_DH_NAME, retval); - if (retval < 0) - return SCSI_DH_DEV_TEMP_BUSY; - } else { - sdev_printk(KERN_INFO, sdev, "%s: stpg failed\n", - ALUA_DH_NAME); - scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr); - } - } - /* Retry RTPG */ - return SCSI_DH_RETRY; -} - static void alua_rtpg_work(struct work_struct *work) { struct alua_dh_data *h = @@ -670,56 +179,41 @@ static void alua_rtpg_work(struct work_struct *work) int err = SCSI_DH_OK; struct alua_queue_data *qdata, *tmp; unsigned long flags; + int ret; spin_lock_irqsave(&h->lock, flags); h->flags |= ALUA_PG_RUNNING; if (h->flags & ALUA_PG_RUN_RTPG) { - int state = h->state; h->flags &= ~ALUA_PG_RUN_RTPG; spin_unlock_irqrestore(&h->lock, flags); - if (state == SCSI_ACCESS_STATE_TRANSITIONING) { - if (alua_tur(sdev) == SCSI_DH_RETRY) { - spin_lock_irqsave(&h->lock, flags); - h->flags &= ~ALUA_PG_RUNNING; - h->flags |= ALUA_PG_RUN_RTPG; - if (!h->interval) - h->interval = ALUA_RTPG_RETRY_DELAY; - spin_unlock_irqrestore(&h->lock, flags); - queue_delayed_work(kaluad_wq, &h->rtpg_work, - h->interval * HZ); - return; - } - /* Send RTPG on failure or if TUR indicates SUCCESS */ - } - err = alua_rtpg(sdev); - spin_lock_irqsave(&h->lock, flags); - - if (err == SCSI_DH_RETRY || h->flags & ALUA_PG_RUN_RTPG) { + ret = scsi_alua_rtpg_run(sdev); + if (ret == -EAGAIN) { + spin_lock_irqsave(&h->lock, flags); h->flags &= ~ALUA_PG_RUNNING; - if (err == SCSI_DH_IMM_RETRY) - h->interval = 0; - else if (!h->interval && !(h->flags & ALUA_PG_RUN_RTPG)) - h->interval = ALUA_RTPG_RETRY_DELAY; h->flags |= ALUA_PG_RUN_RTPG; spin_unlock_irqrestore(&h->lock, flags); - goto queue_rtpg; + queue_delayed_work(kaluad_wq, &h->rtpg_work, + sdev->alua->interval * HZ); + return; } - if (err != SCSI_DH_OK) - h->flags &= ~ALUA_PG_RUN_STPG; + if (err != 0) + h->flags &= ~ALUA_PG_RUN_STPG; } + spin_lock_irqsave(&h->lock, flags); if (h->flags & ALUA_PG_RUN_STPG) { h->flags &= ~ALUA_PG_RUN_STPG; spin_unlock_irqrestore(&h->lock, flags); - err = alua_stpg(sdev); - spin_lock_irqsave(&h->lock, flags); - if (err == SCSI_DH_RETRY || h->flags & ALUA_PG_RUN_RTPG) { + ret = scsi_alua_stpg_run(sdev, h->flags & ALUA_OPTIMIZE_STPG); + if (err == -EAGAIN || h->flags & ALUA_PG_RUN_RTPG) { + spin_lock_irqsave(&h->lock, flags); h->flags |= ALUA_PG_RUN_RTPG; - h->interval = 0; h->flags &= ~ALUA_PG_RUNNING; spin_unlock_irqrestore(&h->lock, flags); goto queue_rtpg; } + } else { + spin_unlock_irqrestore(&h->lock, flags); } list_splice_init(&h->rtpg_list, &qdata_list); @@ -728,8 +222,6 @@ static void alua_rtpg_work(struct work_struct *work) * Re-enable the device for the next attempt. */ h->disabled = false; - spin_unlock_irqrestore(&h->lock, flags); - list_for_each_entry_safe(qdata, tmp, &qdata_list, entry) { list_del(&qdata->entry); @@ -745,7 +237,7 @@ static void alua_rtpg_work(struct work_struct *work) return; queue_rtpg: - queue_delayed_work(kaluad_wq, &h->rtpg_work, h->interval * HZ); + queue_delayed_work(kaluad_wq, &h->rtpg_work, sdev->alua->interval * HZ); } /** @@ -809,7 +301,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h) mutex_lock(&h->init_mutex); h->disabled = false; - tpgs = alua_check_tpgs(sdev); + tpgs = scsi_alua_check_tpgs(sdev); if (tpgs != TPGS_MODE_NONE) err = alua_check_vpd(sdev, h, tpgs); h->init_error = err; @@ -898,34 +390,6 @@ static void alua_check(struct scsi_device *sdev, bool force) alua_rtpg_queue(sdev, NULL, force); } -/* - * alua_prep_fn - request callback - * - * Fail I/O to all paths not in state - * active/optimized or active/non-optimized. - */ -static blk_status_t alua_prep_fn(struct scsi_device *sdev, struct request *req) -{ - struct alua_dh_data *h = sdev->handler_data; - unsigned long flags; - unsigned char state; - - spin_lock_irqsave(&h->lock, flags); - state = h->state; - spin_unlock_irqrestore(&h->lock, flags); - - switch (state) { - case SCSI_ACCESS_STATE_OPTIMAL: - case SCSI_ACCESS_STATE_ACTIVE: - case SCSI_ACCESS_STATE_LBA: - case SCSI_ACCESS_STATE_TRANSITIONING: - return BLK_STS_OK; - default: - req->rq_flags |= RQF_QUIET; - return BLK_STS_IOERR; - } -} - static void alua_rescan(struct scsi_device *sdev) { struct alua_dh_data *h = sdev->handler_data; @@ -953,8 +417,6 @@ static int alua_bus_attach(struct scsi_device *sdev) mutex_init(&h->init_mutex); - h->state = SCSI_ACCESS_STATE_OPTIMAL; - h->valid_states = TPGS_SUPPORT_ALL; if (optimize_stpg) h->flags |= ALUA_OPTIMIZE_STPG; @@ -986,7 +448,7 @@ static struct scsi_device_handler alua_dh = { .module = THIS_MODULE, .attach = alua_bus_attach, .detach = alua_bus_detach, - .prep_fn = alua_prep_fn, + .prep_fn = scsi_alua_prep_fn, .check_sense = alua_check_sense, .activate = alua_activate, .rescan = alua_rescan, -- 2.43.5

