File scsi-disk-fold-SG_IO-errors-back-into-re.patch of Package qemu.19783

From: Hannes Reinecke <hare@suse.de>
Date: Wed, 11 Nov 2020 17:34:45 +0100
Subject: 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 <hare@suse.de>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
 hw/scsi/scsi-disk.c  | 37 ++++++++++++++++++++++++++++++-------
 hw/scsi/trace-events |  1 +
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index c672e521bb2d4a1703d3b2b78adc..0c1befa2ddffd3b95153a44a743d 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 bce865c2222b0ece52d16ab1d90a..beae309d3000c0a401cec55be37d 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"
openSUSE Build Service is sponsored by