[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:
Родитель
4e2ef86cd5
Коммит
96e6586556
|
@ -60,11 +60,17 @@ struct alua_dh_data {
|
|||
int bufflen;
|
||||
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
|
||||
int senselen;
|
||||
struct scsi_device *sdev;
|
||||
activate_complete callback_fn;
|
||||
void *callback_data;
|
||||
};
|
||||
|
||||
#define ALUA_POLICY_SWITCH_CURRENT 0
|
||||
#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)
|
||||
{
|
||||
struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
|
||||
|
@ -230,19 +236,72 @@ done:
|
|||
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
|
||||
* @sdev: sdev the command should be sent to
|
||||
*
|
||||
* 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 unsigned submit_stpg(struct scsi_device *sdev, struct alua_dh_data *h)
|
||||
static unsigned submit_stpg(struct alua_dh_data *h)
|
||||
{
|
||||
struct request *rq;
|
||||
int err = SCSI_DH_RES_TEMP_UNAVAIL;
|
||||
int stpg_len = 8;
|
||||
struct scsi_device *sdev = h->sdev;
|
||||
|
||||
/* Prepare the data buffer */
|
||||
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);
|
||||
if (!rq)
|
||||
goto done;
|
||||
return SCSI_DH_RES_TEMP_UNAVAIL;
|
||||
|
||||
/* Prepare the command. */
|
||||
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;
|
||||
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
|
||||
rq->sense_len = h->senselen = 0;
|
||||
rq->end_io_data = h;
|
||||
|
||||
err = blk_execute_rq(rq->q, NULL, rq, 1);
|
||||
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:
|
||||
blk_execute_rq_nowait(rq->q, NULL, rq, 1, stpg_endio);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -476,50 +527,6 @@ static int alua_check_sense(struct scsi_device *sdev,
|
|||
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
|
||||
* @sdev: the device to be evaluated.
|
||||
|
@ -664,8 +671,14 @@ static int alua_activate(struct scsi_device *sdev,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (h->tpgs & TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED)
|
||||
err = alua_stpg(sdev, TPGS_STATE_OPTIMIZED, h);
|
||||
if (h->tpgs & TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED) {
|
||||
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:
|
||||
if (fn)
|
||||
|
@ -748,6 +761,7 @@ static int alua_bus_attach(struct scsi_device *sdev)
|
|||
h->rel_port = -1;
|
||||
h->buff = h->inq;
|
||||
h->bufflen = ALUA_INQUIRY_SIZE;
|
||||
h->sdev = sdev;
|
||||
|
||||
err = alua_initialize(sdev, h);
|
||||
if (err != SCSI_DH_OK)
|
||||
|
|
Загрузка…
Ссылка в новой задаче