mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 19:56:18 +00:00
[SCSI] scsi_dh: Make alua hardware handler's activate() async
Make the activate function asynchronous by using blk_execute_rq_nowait() Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
4e2ef86cd5
commit
96e6586556
1 changed files with 73 additions and 59 deletions
|
@ -60,11 +60,17 @@ struct alua_dh_data {
|
||||||
int bufflen;
|
int bufflen;
|
||||||
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
|
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
|
||||||
int senselen;
|
int senselen;
|
||||||
|
struct scsi_device *sdev;
|
||||||
|
activate_complete callback_fn;
|
||||||
|
void *callback_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ALUA_POLICY_SWITCH_CURRENT 0
|
#define ALUA_POLICY_SWITCH_CURRENT 0
|
||||||
#define ALUA_POLICY_SWITCH_ALL 1
|
#define ALUA_POLICY_SWITCH_ALL 1
|
||||||
|
|
||||||
|
static char print_alua_state(int);
|
||||||
|
static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *);
|
||||||
|
|
||||||
static inline struct alua_dh_data *get_alua_data(struct scsi_device *sdev)
|
static inline struct alua_dh_data *get_alua_data(struct scsi_device *sdev)
|
||||||
{
|
{
|
||||||
struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
|
struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
|
||||||
|
@ -230,19 +236,72 @@ done:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* alua_stpg - Evaluate SET TARGET GROUP STATES
|
||||||
|
* @sdev: the device to be evaluated
|
||||||
|
* @state: the new target group state
|
||||||
|
*
|
||||||
|
* Send a SET TARGET GROUP STATES command to the device.
|
||||||
|
* We only have to test here if we should resubmit the command;
|
||||||
|
* any other error is assumed as a failure.
|
||||||
|
*/
|
||||||
|
static void stpg_endio(struct request *req, int error)
|
||||||
|
{
|
||||||
|
struct alua_dh_data *h = req->end_io_data;
|
||||||
|
struct scsi_sense_hdr sense_hdr;
|
||||||
|
unsigned err = SCSI_DH_IO;
|
||||||
|
|
||||||
|
if (error || host_byte(req->errors) != DID_OK ||
|
||||||
|
msg_byte(req->errors) != COMMAND_COMPLETE)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (err == SCSI_DH_IO && h->senselen > 0) {
|
||||||
|
err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
|
||||||
|
&sense_hdr);
|
||||||
|
if (!err) {
|
||||||
|
err = SCSI_DH_IO;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
err = alua_check_sense(h->sdev, &sense_hdr);
|
||||||
|
if (err == ADD_TO_MLQUEUE) {
|
||||||
|
err = SCSI_DH_RETRY;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
sdev_printk(KERN_INFO, h->sdev,
|
||||||
|
"%s: stpg sense code: %02x/%02x/%02x\n",
|
||||||
|
ALUA_DH_NAME, sense_hdr.sense_key,
|
||||||
|
sense_hdr.asc, sense_hdr.ascq);
|
||||||
|
err = SCSI_DH_IO;
|
||||||
|
}
|
||||||
|
if (err == SCSI_DH_OK) {
|
||||||
|
h->state = TPGS_STATE_OPTIMIZED;
|
||||||
|
sdev_printk(KERN_INFO, h->sdev,
|
||||||
|
"%s: port group %02x switched to state %c\n",
|
||||||
|
ALUA_DH_NAME, h->group_id,
|
||||||
|
print_alua_state(h->state));
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
blk_put_request(req);
|
||||||
|
if (h->callback_fn) {
|
||||||
|
h->callback_fn(h->callback_data, err);
|
||||||
|
h->callback_fn = h->callback_data = NULL;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* submit_stpg - Issue a SET TARGET GROUP STATES command
|
* submit_stpg - Issue a SET TARGET GROUP STATES command
|
||||||
* @sdev: sdev the command should be sent to
|
|
||||||
*
|
*
|
||||||
* Currently we're only setting the current target port group state
|
* Currently we're only setting the current target port group state
|
||||||
* to 'active/optimized' and let the array firmware figure out
|
* to 'active/optimized' and let the array firmware figure out
|
||||||
* the states of the remaining groups.
|
* the states of the remaining groups.
|
||||||
*/
|
*/
|
||||||
static unsigned submit_stpg(struct scsi_device *sdev, struct alua_dh_data *h)
|
static unsigned submit_stpg(struct alua_dh_data *h)
|
||||||
{
|
{
|
||||||
struct request *rq;
|
struct request *rq;
|
||||||
int err = SCSI_DH_RES_TEMP_UNAVAIL;
|
int err = SCSI_DH_RES_TEMP_UNAVAIL;
|
||||||
int stpg_len = 8;
|
int stpg_len = 8;
|
||||||
|
struct scsi_device *sdev = h->sdev;
|
||||||
|
|
||||||
/* Prepare the data buffer */
|
/* Prepare the data buffer */
|
||||||
memset(h->buff, 0, stpg_len);
|
memset(h->buff, 0, stpg_len);
|
||||||
|
@ -252,7 +311,7 @@ static unsigned submit_stpg(struct scsi_device *sdev, struct alua_dh_data *h)
|
||||||
|
|
||||||
rq = get_alua_req(sdev, h->buff, stpg_len, WRITE);
|
rq = get_alua_req(sdev, h->buff, stpg_len, WRITE);
|
||||||
if (!rq)
|
if (!rq)
|
||||||
goto done;
|
return SCSI_DH_RES_TEMP_UNAVAIL;
|
||||||
|
|
||||||
/* Prepare the command. */
|
/* Prepare the command. */
|
||||||
rq->cmd[0] = MAINTENANCE_OUT;
|
rq->cmd[0] = MAINTENANCE_OUT;
|
||||||
|
@ -266,17 +325,9 @@ static unsigned submit_stpg(struct scsi_device *sdev, struct alua_dh_data *h)
|
||||||
rq->sense = h->sense;
|
rq->sense = h->sense;
|
||||||
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
|
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
|
||||||
rq->sense_len = h->senselen = 0;
|
rq->sense_len = h->senselen = 0;
|
||||||
|
rq->end_io_data = h;
|
||||||
|
|
||||||
err = blk_execute_rq(rq->q, NULL, rq, 1);
|
blk_execute_rq_nowait(rq->q, NULL, rq, 1, stpg_endio);
|
||||||
if (err == -EIO) {
|
|
||||||
sdev_printk(KERN_INFO, sdev,
|
|
||||||
"%s: stpg failed with %x\n",
|
|
||||||
ALUA_DH_NAME, rq->errors);
|
|
||||||
h->senselen = rq->sense_len;
|
|
||||||
err = SCSI_DH_IO;
|
|
||||||
}
|
|
||||||
blk_put_request(rq);
|
|
||||||
done:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,50 +527,6 @@ static int alua_check_sense(struct scsi_device *sdev,
|
||||||
return SCSI_RETURN_NOT_HANDLED;
|
return SCSI_RETURN_NOT_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* alua_stpg - Evaluate SET TARGET GROUP STATES
|
|
||||||
* @sdev: the device to be evaluated
|
|
||||||
* @state: the new target group state
|
|
||||||
*
|
|
||||||
* Send a SET TARGET GROUP STATES command to the device.
|
|
||||||
* We only have to test here if we should resubmit the command;
|
|
||||||
* any other error is assumed as a failure.
|
|
||||||
*/
|
|
||||||
static int alua_stpg(struct scsi_device *sdev, int state,
|
|
||||||
struct alua_dh_data *h)
|
|
||||||
{
|
|
||||||
struct scsi_sense_hdr sense_hdr;
|
|
||||||
unsigned err;
|
|
||||||
int retry = ALUA_FAILOVER_RETRIES;
|
|
||||||
|
|
||||||
retry:
|
|
||||||
err = submit_stpg(sdev, h);
|
|
||||||
if (err == SCSI_DH_IO && h->senselen > 0) {
|
|
||||||
err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
|
|
||||||
&sense_hdr);
|
|
||||||
if (!err)
|
|
||||||
return SCSI_DH_IO;
|
|
||||||
err = alua_check_sense(sdev, &sense_hdr);
|
|
||||||
if (retry > 0 && err == ADD_TO_MLQUEUE) {
|
|
||||||
retry--;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
sdev_printk(KERN_INFO, sdev,
|
|
||||||
"%s: stpg sense code: %02x/%02x/%02x\n",
|
|
||||||
ALUA_DH_NAME, sense_hdr.sense_key,
|
|
||||||
sense_hdr.asc, sense_hdr.ascq);
|
|
||||||
err = SCSI_DH_IO;
|
|
||||||
}
|
|
||||||
if (err == SCSI_DH_OK) {
|
|
||||||
h->state = state;
|
|
||||||
sdev_printk(KERN_INFO, sdev,
|
|
||||||
"%s: port group %02x switched to state %c\n",
|
|
||||||
ALUA_DH_NAME, h->group_id,
|
|
||||||
print_alua_state(h->state) );
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* alua_rtpg - Evaluate REPORT TARGET GROUP STATES
|
* alua_rtpg - Evaluate REPORT TARGET GROUP STATES
|
||||||
* @sdev: the device to be evaluated.
|
* @sdev: the device to be evaluated.
|
||||||
|
@ -664,8 +671,14 @@ static int alua_activate(struct scsi_device *sdev,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h->tpgs & TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED)
|
if (h->tpgs & TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED) {
|
||||||
err = alua_stpg(sdev, TPGS_STATE_OPTIMIZED, h);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (fn)
|
if (fn)
|
||||||
|
@ -748,6 +761,7 @@ static int alua_bus_attach(struct scsi_device *sdev)
|
||||||
h->rel_port = -1;
|
h->rel_port = -1;
|
||||||
h->buff = h->inq;
|
h->buff = h->inq;
|
||||||
h->bufflen = ALUA_INQUIRY_SIZE;
|
h->bufflen = ALUA_INQUIRY_SIZE;
|
||||||
|
h->sdev = sdev;
|
||||||
|
|
||||||
err = alua_initialize(sdev, h);
|
err = alua_initialize(sdev, h);
|
||||||
if (err != SCSI_DH_OK)
|
if (err != SCSI_DH_OK)
|
||||||
|
|
Loading…
Reference in a new issue