From: Hannes Reinecke Date: Wed, 11 Nov 2020 16:34:45 +0000 (+0100) Subject: scsi-disk: fold SG_IO errors back into request status X-Git-Tag: upstream/4.2.1~84 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=72894334c4eda24b08fcf7bf0462554933e4f53a;p=tools%2Fqemu-arm-static.git scsi-disk: fold SG_IO errors back into request status References: bsc#1178049 When SG_IO returns with a non-zero 'host_status' or 'status' we should be folding these values into the request status to allow any drivers to signal them back to the guest. Signed-off-by: Hannes Reinecke Signed-off-by: Bruce Rogers --- diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index c672e521b..0c1befa2d 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -81,7 +81,7 @@ typedef struct SCSIDiskReq { struct iovec iov; QEMUIOVector qiov; BlockAcctCookie acct; - unsigned char *status; + uint32_t status; } SCSIDiskReq; #define SCSI_DISK_F_REMOVABLE 0 @@ -194,7 +194,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->status) { return scsi_handle_rw_error(r, -ret, acct_failed); } @@ -458,11 +458,12 @@ 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); - if (scsi_sense_buf_is_guest_recoverable(r->req.sense, sizeof(r->req.sense))) { + assert(r->status); + if ((r->status >> 8) || + 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->status); return true; } error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense)); @@ -2695,8 +2696,26 @@ typedef struct SCSIBlockReq { /* CDB passed to SG_IO. */ uint8_t cdb[16]; + BlockCompletionFunc *cb; + void *cb_opaque; } SCSIBlockReq; +static void sgio_aio_complete(void *opaque, int ret) +{ + SCSIBlockReq *req = (SCSIBlockReq *)opaque; + SCSIDiskReq *r = &req->req; + SCSISense sense; + + trace_scsi_disk_aio_sgio_done(r->req.tag, ret, req->io_header.status, + req->io_header.host_status); + r->status = sg_io_sense_from_errno(-ret, &req->io_header, &sense); + if ((r->status & 0xff) == 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, @@ -2777,9 +2796,14 @@ static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req, io_header->timeout = 5000; 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, + sgio_aio_complete, req); assert(aiocb != NULL); return aiocb; } @@ -2893,7 +2917,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); } diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events index bce865c22..beae309d3 100644 --- a/hw/scsi/trace-events +++ b/hw/scsi/trace-events @@ -328,6 +328,7 @@ scsi_disk_dma_command_READ(uint64_t lba, uint32_t len) "Read (sector %" PRId64 " scsi_disk_dma_command_WRITE(const char *cmd, uint64_t lba, int len) "Write %s(sector %" PRId64 ", count %u)" scsi_disk_new_request(uint32_t lun, uint32_t tag, const char *line) "Command: lun=%d tag=0x%x data=%s" scsi_disk_aio_sgio_command(uint32_t tag, uint8_t cmd, uint64_t lba, int len, uint32_t timeout) "disk aio sgio: tag=0x%x cmd 0x%x (sector %" PRId64 ", count %d) timeout %u" +scsi_disk_aio_sgio_done(uint32_t tag, int ret, uint8_t status, uint8_t host_status) "disk aio sgio: cmd 0x%x ret %d status 0x%x host_status 0x%x" # scsi-generic.c scsi_generic_command_complete_noio(void *req, uint32_t tag, uint8_t status, uint8_t host_status) "Command complete %p tag=0x%x status=0x%x host_status=0x%x"