Add a separate sg_io callback to allow us to evaluate the various states returned by the SG_IO ioctl.
Signed-off-by: Hannes Reinecke <h...@suse.de> --- hw/scsi/scsi-disk.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index dd23a38d6a..5d6c892f29 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -76,7 +76,6 @@ typedef struct SCSIDiskReq { struct iovec iov; QEMUIOVector qiov; BlockAcctCookie acct; - unsigned char *status; } SCSIDiskReq; #define SCSI_DISK_F_REMOVABLE 0 @@ -188,7 +187,7 @@ static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed) return true; } - if (ret < 0 || (r->status && *r->status)) { + if (ret < 0 || r->req.status) { return scsi_handle_rw_error(r, -ret, acct_failed); } @@ -452,11 +451,11 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed) * whether the error has to be handled by the guest or should rather * pause the host. */ - assert(r->status && *r->status); + assert(r->req.status); if (scsi_sense_buf_is_guest_recoverable(r->req.sense, sizeof(r->req.sense))) { /* These errors are handled by guest. */ sdc->update_sense(&r->req); - scsi_req_complete(&r->req, *r->status); + scsi_req_complete(&r->req, r->req.status); return true; } error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense)); @@ -2688,8 +2687,24 @@ typedef struct SCSIBlockReq { /* CDB passed to SG_IO. */ uint8_t cdb[16]; + BlockCompletionFunc *cb; + void *cb_opaque; } SCSIBlockReq; +static void scsi_block_sgio_complete(void *opaque, int ret) +{ + SCSIBlockReq *req = (SCSIBlockReq *)opaque; + SCSIDiskReq *r = &req->req; + SCSISense sense; + + r->req.status = sg_io_sense_from_errno(-ret, &req->io_header, &sense); + if (r->req.status == CHECK_CONDITION && + req->io_header.status != CHECK_CONDITION) + scsi_req_build_sense(&r->req, sense); + + req->cb(req->cb_opaque, ret); +} + static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req, int64_t offset, QEMUIOVector *iov, int direction, @@ -2768,9 +2783,11 @@ static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req, io_header->timeout = s->qdev.io_timeout * 1000; io_header->usr_ptr = r; io_header->flags |= SG_FLAG_DIRECT_IO; + req->cb = cb; + req->cb_opaque = opaque; trace_scsi_disk_aio_sgio_command(r->req.tag, req->cdb[0], lba, nb_logical_blocks, io_header->timeout); - aiocb = blk_aio_ioctl(s->qdev.conf.blk, SG_IO, io_header, cb, opaque); + aiocb = blk_aio_ioctl(s->qdev.conf.blk, SG_IO, io_header, scsi_block_sgio_complete, req); assert(aiocb != NULL); return aiocb; } @@ -2884,7 +2901,6 @@ static int32_t scsi_block_dma_command(SCSIRequest *req, uint8_t *buf) return 0; } - r->req.status = &r->io_header.status; return scsi_disk_dma_command(req, buf); } -- 2.16.4