mirror of https://github.com/proxmox/mirror_qemu
scsi: pass status when completing
A small improvement in the SCSI request API. Pass the status at the time the request is completed, so that we can assert that no request is completed twice. This would have detected the problem fixed in the previous patch. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>master
parent
05751d3ff7
commit
682a9b213c
|
@ -682,9 +682,10 @@ void scsi_req_print(SCSIRequest *req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scsi_req_complete(SCSIRequest *req)
|
void scsi_req_complete(SCSIRequest *req, int status)
|
||||||
{
|
{
|
||||||
assert(req->status != -1);
|
assert(req->status == -1);
|
||||||
|
req->status = status;
|
||||||
scsi_req_ref(req);
|
scsi_req_ref(req);
|
||||||
scsi_req_dequeue(req);
|
scsi_req_dequeue(req);
|
||||||
req->bus->ops->complete(req, req->status);
|
req->bus->ops->complete(req, req->status);
|
||||||
|
@ -706,11 +707,10 @@ void scsi_req_cancel(SCSIRequest *req)
|
||||||
|
|
||||||
void scsi_req_abort(SCSIRequest *req, int status)
|
void scsi_req_abort(SCSIRequest *req, int status)
|
||||||
{
|
{
|
||||||
req->status = status;
|
|
||||||
if (req->dev && req->dev->info->cancel_io) {
|
if (req->dev && req->dev->info->cancel_io) {
|
||||||
req->dev->info->cancel_io(req);
|
req->dev->info->cancel_io(req);
|
||||||
}
|
}
|
||||||
scsi_req_complete(req);
|
scsi_req_complete(req, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scsi_device_purge_requests(SCSIDevice *sdev)
|
void scsi_device_purge_requests(SCSIDevice *sdev)
|
||||||
|
|
|
@ -102,21 +102,15 @@ static void scsi_disk_clear_sense(SCSIDiskState *s)
|
||||||
memset(&s->sense, 0, sizeof(s->sense));
|
memset(&s->sense, 0, sizeof(s->sense));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scsi_req_set_status(SCSIDiskReq *r, int status, SCSISense sense)
|
|
||||||
{
|
|
||||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
|
||||||
|
|
||||||
r->req.status = status;
|
|
||||||
s->sense = sense;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Helper function for command completion. */
|
/* Helper function for command completion. */
|
||||||
static void scsi_command_complete(SCSIDiskReq *r, int status, SCSISense sense)
|
static void scsi_command_complete(SCSIDiskReq *r, int status, SCSISense sense)
|
||||||
{
|
{
|
||||||
|
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
||||||
|
|
||||||
DPRINTF("Command complete tag=0x%x status=%d sense=%d/%d/%d\n",
|
DPRINTF("Command complete tag=0x%x status=%d sense=%d/%d/%d\n",
|
||||||
r->req.tag, status, sense.key, sense.asc, sense.ascq);
|
r->req.tag, status, sense.key, sense.asc, sense.ascq);
|
||||||
scsi_req_set_status(r, status, sense);
|
s->sense = sense;
|
||||||
scsi_req_complete(&r->req);
|
scsi_req_complete(&r->req, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cancel a pending data transfer. */
|
/* Cancel a pending data transfer. */
|
||||||
|
@ -969,7 +963,6 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
|
||||||
scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE));
|
scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
scsi_req_set_status(r, GOOD, SENSE_CODE(NO_SENSE));
|
|
||||||
return buflen;
|
return buflen;
|
||||||
|
|
||||||
not_ready:
|
not_ready:
|
||||||
|
|
|
@ -115,6 +115,7 @@ static void scsi_free_request(SCSIRequest *req)
|
||||||
/* Helper function for command completion. */
|
/* Helper function for command completion. */
|
||||||
static void scsi_command_complete(void *opaque, int ret)
|
static void scsi_command_complete(void *opaque, int ret)
|
||||||
{
|
{
|
||||||
|
int status;
|
||||||
SCSIGenericReq *r = (SCSIGenericReq *)opaque;
|
SCSIGenericReq *r = (SCSIGenericReq *)opaque;
|
||||||
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
|
SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
|
||||||
|
|
||||||
|
@ -126,36 +127,37 @@ static void scsi_command_complete(void *opaque, int ret)
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case -EDOM:
|
case -EDOM:
|
||||||
r->req.status = TASK_SET_FULL;
|
status = TASK_SET_FULL;
|
||||||
break;
|
break;
|
||||||
case -EINVAL:
|
case -EINVAL:
|
||||||
r->req.status = CHECK_CONDITION;
|
status = CHECK_CONDITION;
|
||||||
scsi_set_sense(s, SENSE_CODE(INVALID_FIELD));
|
scsi_set_sense(s, SENSE_CODE(INVALID_FIELD));
|
||||||
break;
|
break;
|
||||||
case -ENOMEM:
|
case -ENOMEM:
|
||||||
r->req.status = CHECK_CONDITION;
|
status = CHECK_CONDITION;
|
||||||
scsi_set_sense(s, SENSE_CODE(TARGET_FAILURE));
|
scsi_set_sense(s, SENSE_CODE(TARGET_FAILURE));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
r->req.status = CHECK_CONDITION;
|
status = CHECK_CONDITION;
|
||||||
scsi_set_sense(s, SENSE_CODE(IO_ERROR));
|
scsi_set_sense(s, SENSE_CODE(IO_ERROR));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
|
if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
|
||||||
r->req.status = BUSY;
|
status = BUSY;
|
||||||
BADF("Driver Timeout\n");
|
BADF("Driver Timeout\n");
|
||||||
} else if (r->io_header.status)
|
} else if (r->io_header.status) {
|
||||||
r->req.status = r->io_header.status;
|
status = r->io_header.status;
|
||||||
else if (s->driver_status & SG_ERR_DRIVER_SENSE)
|
} else if (s->driver_status & SG_ERR_DRIVER_SENSE) {
|
||||||
r->req.status = CHECK_CONDITION;
|
status = CHECK_CONDITION;
|
||||||
else
|
} else {
|
||||||
r->req.status = GOOD;
|
status = GOOD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
|
DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
|
||||||
r, r->req.tag, r->req.status);
|
r, r->req.tag, status);
|
||||||
|
|
||||||
scsi_req_complete(&r->req);
|
scsi_req_complete(&r->req, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cancel a pending data transfer. */
|
/* Cancel a pending data transfer. */
|
||||||
|
@ -341,8 +343,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
|
||||||
if (cmd[0] != REQUEST_SENSE && req->lun != s->lun) {
|
if (cmd[0] != REQUEST_SENSE && req->lun != s->lun) {
|
||||||
DPRINTF("Unimplemented LUN %d\n", req->lun);
|
DPRINTF("Unimplemented LUN %d\n", req->lun);
|
||||||
scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED));
|
scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED));
|
||||||
r->req.status = CHECK_CONDITION;
|
scsi_req_complete(&r->req, CHECK_CONDITION);
|
||||||
scsi_req_complete(&r->req);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,7 @@ int scsi_req_parse(SCSIRequest *req, uint8_t *buf);
|
||||||
void scsi_req_print(SCSIRequest *req);
|
void scsi_req_print(SCSIRequest *req);
|
||||||
void scsi_req_continue(SCSIRequest *req);
|
void scsi_req_continue(SCSIRequest *req);
|
||||||
void scsi_req_data(SCSIRequest *req, int len);
|
void scsi_req_data(SCSIRequest *req, int len);
|
||||||
void scsi_req_complete(SCSIRequest *req);
|
void scsi_req_complete(SCSIRequest *req, int status);
|
||||||
uint8_t *scsi_req_get_buf(SCSIRequest *req);
|
uint8_t *scsi_req_get_buf(SCSIRequest *req);
|
||||||
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
|
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
|
||||||
void scsi_req_abort(SCSIRequest *req, int status);
|
void scsi_req_abort(SCSIRequest *req, int status);
|
||||||
|
|
Loading…
Reference in New Issue