[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 09/10] scsi: inline sg_io_sense_from_errno() into the callers.
From: |
Paolo Bonzini |
Subject: |
[PATCH 09/10] scsi: inline sg_io_sense_from_errno() into the callers. |
Date: |
Wed, 24 Feb 2021 19:24:52 +0100 |
From: Hannes Reinecke <hare@suse.de>
Currently sg_io_sense_from_errno() converts the two input parameters
'errno' and 'io_hdr' into sense code and SCSI status. Having
split the function off into scsi_sense_from_errno() and
scsi_sense_from_host_status(), both of which are available generically,
we now inline the logic in the callers so that scsi-disk and
scsi-generic will be able to pass host_status to the HBA.
Signed-off-by: Hannes Reinecke <hare@suse.de>
Message-Id: <20201116184041.60465-7-hare@suse.de>
[Put together from "scsi-disk: Add sg_io callback to evaluate status"
and what remains of "scsi: split sg_io_sense_from_errno() in two functions",
with many other fixes. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/scsi/scsi-disk.c | 47 +++++++++++++++++++++++++++++++++++++-----
hw/scsi/scsi-generic.c | 22 ++++++++++++++------
include/scsi/utils.h | 3 ---
scsi/qemu-pr-helper.c | 24 ++++++++++++++-------
scsi/utils.c | 23 ---------------------
5 files changed, 75 insertions(+), 44 deletions(-)
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index a5a58d7db3..ceaf78b423 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -77,7 +77,6 @@ typedef struct SCSIDiskReq {
struct iovec iov;
QEMUIOVector qiov;
BlockAcctCookie acct;
- unsigned char *status;
} SCSIDiskReq;
#define SCSI_DISK_F_REMOVABLE 0
@@ -261,8 +260,6 @@ static bool scsi_disk_req_check_error(SCSIDiskReq *r, int
ret, bool acct_failed)
if (ret < 0) {
return scsi_handle_rw_error(r, ret, acct_failed);
- } else if (r->status && *r->status) {
- return scsi_handle_rw_error(r, *r->status, acct_failed);
}
return false;
@@ -2697,8 +2694,47 @@ 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;
+ SCSIDevice *s = r->req.dev;
+ sg_io_hdr_t *io_hdr = &req->io_header;
+ SCSISense sense;
+
+ if (ret == 0) {
+ if (io_hdr->host_status != SCSI_HOST_OK) {
+ ret = scsi_sense_from_host_status(io_hdr->host_status, &sense);
+ if (ret == CHECK_CONDITION) {
+ scsi_req_build_sense(&r->req, sense);
+ }
+ } else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
+ ret = BUSY;
+ } else {
+ ret = io_hdr->status;
+ }
+
+ if (ret > 0) {
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
+ if (scsi_handle_rw_error(r, ret, true)) {
+ aio_context_release(blk_get_aio_context(s->conf.blk));
+ scsi_req_unref(&r->req);
+ return;
+ }
+ aio_context_release(blk_get_aio_context(s->conf.blk));
+
+ /* Ignore error. */
+ ret = 0;
+ }
+ }
+
+ req->cb(req->cb_opaque, ret);
+}
+
static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req,
int64_t offset, QEMUIOVector *iov,
int direction,
@@ -2777,9 +2813,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;
}
@@ -2893,7 +2931,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/scsi-generic.c b/hw/scsi/scsi-generic.c
index cf7e11cf44..716caf0d22 100644
--- a/hw/scsi/scsi-generic.c
+++ b/hw/scsi/scsi-generic.c
@@ -75,6 +75,7 @@ static void scsi_command_complete_noio(SCSIGenericReq *r, int
ret)
{
int status;
SCSISense sense;
+ sg_io_hdr_t *io_hdr = &r->io_header;
assert(r->req.aiocb == NULL);
@@ -82,15 +83,24 @@ static void scsi_command_complete_noio(SCSIGenericReq *r,
int ret)
scsi_req_cancel_complete(&r->req);
goto done;
}
- status = sg_io_sense_from_errno(-ret, &r->io_header, &sense);
- if (status == CHECK_CONDITION) {
- if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
- r->req.sense_len = r->io_header.sb_len_wr;
- } else {
+ if (ret < 0) {
+ status = scsi_sense_from_errno(-ret, &sense);
+ if (status == CHECK_CONDITION) {
+ scsi_req_build_sense(&r->req, sense);
+ }
+ } else if (io_hdr->host_status != SCSI_HOST_OK) {
+ status = scsi_sense_from_host_status(io_hdr->host_status, &sense);
+ if (status == CHECK_CONDITION) {
scsi_req_build_sense(&r->req, sense);
}
+ } else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
+ status = BUSY;
+ } else {
+ status = io_hdr->status;
+ if (io_hdr->driver_status & SG_ERR_DRIVER_SENSE) {
+ r->req.sense_len = io_hdr->sb_len_wr;
+ }
}
-
trace_scsi_generic_command_complete_noio(r, r->req.tag, status);
scsi_req_complete(&r->req, status);
diff --git a/include/scsi/utils.h b/include/scsi/utils.h
index 9080d65e27..d5c8efa16e 100644
--- a/include/scsi/utils.h
+++ b/include/scsi/utils.h
@@ -139,9 +139,6 @@ int scsi_cdb_length(uint8_t *buf);
#ifdef CONFIG_LINUX
#define SG_ERR_DRIVER_TIMEOUT 0x06
#define SG_ERR_DRIVER_SENSE 0x08
-
-int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
- SCSISense *sense);
#endif
int scsi_sense_from_errno(int errno_value, SCSISense *sense);
diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c
index 2733d92f2d..0cb2bddd61 100644
--- a/scsi/qemu-pr-helper.c
+++ b/scsi/qemu-pr-helper.c
@@ -149,19 +149,29 @@ static int do_sgio_worker(void *opaque)
io_hdr.dxferp = (char *)data->buf;
io_hdr.dxfer_len = data->sz;
ret = ioctl(data->fd, SG_IO, &io_hdr);
- status = sg_io_sense_from_errno(ret < 0 ? errno : 0, &io_hdr,
- &sense_code);
+
+ if (ret < 0) {
+ status = scsi_sense_from_errno(errno, &sense_code);
+ if (status == CHECK_CONDITION) {
+ scsi_build_sense(data->sense, sense_code);
+ }
+ } else if (io_hdr.host_status != SCSI_HOST_OK) {
+ status = scsi_sense_from_host_status(io_hdr.host_status, &sense_code);
+ if (status == CHECK_CONDITION) {
+ scsi_build_sense(data->sense, sense_code);
+ }
+ } else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
+ status = BUSY;
+ } else {
+ status = io_hdr.status;
+ }
+
if (status == GOOD) {
data->sz -= io_hdr.resid;
} else {
data->sz = 0;
}
- if (status == CHECK_CONDITION &&
- !(io_hdr.driver_status & SG_ERR_DRIVER_SENSE)) {
- scsi_build_sense(data->sense, sense_code);
- }
-
return status;
}
diff --git a/scsi/utils.c b/scsi/utils.c
index 28eb32746e..873e05aeaf 100644
--- a/scsi/utils.c
+++ b/scsi/utils.c
@@ -658,26 +658,3 @@ int scsi_sense_from_host_status(uint8_t host_status,
}
return GOOD;
}
-
-#ifdef CONFIG_LINUX
-int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
- SCSISense *sense)
-{
- if (errno_value != 0) {
- return scsi_sense_from_errno(errno_value, sense);
- } else {
- int status = scsi_sense_from_host_status(io_hdr->host_status, sense);
- if (status) {
- return status;
- } else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
- return BUSY;
- } else if (io_hdr->status) {
- return io_hdr->status;
- } else if (io_hdr->driver_status & SG_ERR_DRIVER_SENSE) {
- return CHECK_CONDITION;
- } else {
- return GOOD;
- }
- }
-}
-#endif
--
2.29.2
- [PATCH 00/11] scsi-generic: error handling overhaul, Paolo Bonzini, 2021/02/24
- [PATCH 02/10] scsi-disk: do not complete requests early for rerror/werror=ignore, Paolo Bonzini, 2021/02/24
- [PATCH 04/10] scsi-disk: pass SCSI status to scsi_handle_rw_error, Paolo Bonzini, 2021/02/24
- [PATCH 03/10] scsi: introduce scsi_sense_from_errno(), Paolo Bonzini, 2021/02/24
- [PATCH 05/10] scsi-disk: pass guest recoverable errors through even for rerror=stop, Paolo Bonzini, 2021/02/24
- [PATCH 07/10] scsi: Rename linux-specific SG_ERR codes to generic SCSI_HOST error codes, Paolo Bonzini, 2021/02/24
- [PATCH 09/10] scsi: inline sg_io_sense_from_errno() into the callers.,
Paolo Bonzini <=
- [PATCH 10/10] scsi: move host_status handling into SCSI drivers, Paolo Bonzini, 2021/02/24
- [PATCH 06/10] scsi: drop 'result' argument from command_complete callback, Paolo Bonzini, 2021/02/24
- [PATCH 01/10] scsi-disk: move scsi_handle_rw_error earlier, Paolo Bonzini, 2021/02/24
- [PATCH 08/10] scsi: Add mapping for generic SCSI_HOST status to sense codes, Paolo Bonzini, 2021/02/24
- Re: [PATCH 00/11] scsi-generic: error handling overhaul, Philippe Mathieu-Daudé, 2021/02/24