From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: hare@suse.de
Subject: [PATCH 10/10] scsi: move host_status handling into SCSI drivers
Date: Wed, 24 Feb 2021 19:24:53 +0100 [thread overview]
Message-ID: <20210224182453.587731-11-pbonzini@redhat.com> (raw)
In-Reply-To: <20210224182453.587731-1-pbonzini@redhat.com>
From: Hannes Reinecke <hare@suse.de>
Some SCSI drivers like virtio have an internal mapping for the
host_status. This patch moves the host_status translation into
the SCSI drivers to allow those drivers to set up the correct
values.
Signed-off-by: Hannes Reinecke <hare@suse.de>.
[Added default handling to avoid touching all drivers. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/scsi/scsi-bus.c | 23 +++++++++++++++++++-
hw/scsi/scsi-disk.c | 7 ++----
hw/scsi/scsi-generic.c | 6 ++----
hw/scsi/virtio-scsi.c | 46 ++++++++++++++++++++++++++++++++++++++++
hw/scsi/vmw_pvscsi.c | 39 ++++++++++++++++++++++++++++++++++
include/hw/scsi/scsi.h | 4 +++-
include/scsi/constants.h | 3 +++
7 files changed, 117 insertions(+), 11 deletions(-)
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index dc4141ec8d..6088601925 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -692,6 +692,7 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
req->lun = lun;
req->hba_private = hba_private;
req->status = -1;
+ req->host_status = -1;
req->ops = reqops;
object_ref(OBJECT(d));
object_ref(OBJECT(qbus->parent));
@@ -1455,6 +1456,17 @@ void scsi_req_print(SCSIRequest *req)
}
}
+static void scsi_req_complete_failed(SCSIRequest *req)
+{
+ SCSISense sense;
+
+ req->status = scsi_sense_from_host_status(req->host_status, &sense);
+ if (req->status == CHECK_CONDITION) {
+ scsi_req_build_sense(req, sense);
+ }
+ req->bus->info->complete(req, 0);
+}
+
void scsi_req_complete(SCSIRequest *req, int status)
{
assert(req->status == -1);
@@ -1483,7 +1495,16 @@ void scsi_req_complete(SCSIRequest *req, int status)
scsi_req_ref(req);
scsi_req_dequeue(req);
- req->bus->info->complete(req, req->resid);
+ if (status == CHECK_HOST_STATUS) {
+ if (req->bus->info->fail) {
+ req->bus->info->fail(req);
+ } else {
+ scsi_req_complete_failed(req);
+ }
+ } else {
+ req->host_status = SCSI_HOST_OK;
+ req->bus->info->complete(req, req->resid);
+ }
/* Cancelled requests might end up being completed instead of cancelled */
notifier_list_notify(&req->cancel_notifiers, req);
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index ceaf78b423..b7e53b1b6f 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2704,14 +2704,11 @@ static void scsi_block_sgio_complete(void *opaque, int ret)
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);
- }
+ ret = CHECK_HOST_STATUS;
+ r->req.host_status = io_hdr->host_status;
} else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
ret = BUSY;
} else {
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
index 716caf0d22..8e26fccf74 100644
--- a/hw/scsi/scsi-generic.c
+++ b/hw/scsi/scsi-generic.c
@@ -89,10 +89,8 @@ static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
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);
- }
+ r->req.host_status = io_hdr->host_status;
+ status = CHECK_HOST_STATUS;
} else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
status = BUSY;
} else {
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 358c0e70b0..6d80730287 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -500,6 +500,51 @@ static void virtio_scsi_complete_cmd_req(VirtIOSCSIReq *req)
virtio_scsi_complete_req(req);
}
+static void virtio_scsi_command_failed(SCSIRequest *r)
+{
+ VirtIOSCSIReq *req = r->hba_private;
+
+ if (r->io_canceled) {
+ return;
+ }
+
+ req->resp.cmd.status = GOOD;
+ switch (r->host_status) {
+ case SCSI_HOST_NO_LUN:
+ req->resp.cmd.response = VIRTIO_SCSI_S_INCORRECT_LUN;
+ break;
+ case SCSI_HOST_BUSY:
+ req->resp.cmd.response = VIRTIO_SCSI_S_BUSY;
+ break;
+ case SCSI_HOST_TIME_OUT:
+ case SCSI_HOST_ABORTED:
+ req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED;
+ break;
+ case SCSI_HOST_BAD_RESPONSE:
+ req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
+ break;
+ case SCSI_HOST_RESET:
+ req->resp.cmd.response = VIRTIO_SCSI_S_RESET;
+ break;
+ case SCSI_HOST_TRANSPORT_DISRUPTED:
+ req->resp.cmd.response = VIRTIO_SCSI_S_TRANSPORT_FAILURE;
+ break;
+ case SCSI_HOST_TARGET_FAILURE:
+ req->resp.cmd.response = VIRTIO_SCSI_S_TARGET_FAILURE;
+ break;
+ case SCSI_HOST_RESERVATION_ERROR:
+ req->resp.cmd.response = VIRTIO_SCSI_S_NEXUS_FAILURE;
+ break;
+ case SCSI_HOST_ALLOCATION_FAILURE:
+ case SCSI_HOST_MEDIUM_ERROR:
+ case SCSI_HOST_ERROR:
+ default:
+ req->resp.cmd.response = VIRTIO_SCSI_S_FAILURE;
+ break;
+ }
+ virtio_scsi_complete_cmd_req(req);
+}
+
static void virtio_scsi_command_complete(SCSIRequest *r, size_t resid)
{
VirtIOSCSIReq *req = r->hba_private;
@@ -908,6 +953,7 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
.max_lun = VIRTIO_SCSI_MAX_LUN,
.complete = virtio_scsi_command_complete,
+ .fail = virtio_scsi_command_failed,
.cancel = virtio_scsi_request_cancelled,
.change = virtio_scsi_change,
.parse_cdb = virtio_scsi_parse_cdb,
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 0da378ed50..1f30cb020a 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -510,6 +510,44 @@ pvscsi_write_sense(PVSCSIRequest *r, uint8_t *sense, int len)
cpu_physical_memory_write(r->req.senseAddr, sense, r->cmp.senseLen);
}
+static void
+pvscsi_command_failed(SCSIRequest *req)
+{
+ PVSCSIRequest *pvscsi_req = req->hba_private;
+ PVSCSIState *s;
+
+ if (!pvscsi_req) {
+ trace_pvscsi_command_complete_not_found(req->tag);
+ return;
+ }
+ s = pvscsi_req->dev;
+
+ switch (req->host_status) {
+ case SCSI_HOST_NO_LUN:
+ pvscsi_req->cmp.hostStatus = BTSTAT_LUNMISMATCH;
+ break;
+ case SCSI_HOST_BUSY:
+ pvscsi_req->cmp.hostStatus = BTSTAT_ABORTQUEUE;
+ break;
+ case SCSI_HOST_TIME_OUT:
+ case SCSI_HOST_ABORTED:
+ pvscsi_req->cmp.hostStatus = BTSTAT_SENTRST;
+ break;
+ case SCSI_HOST_BAD_RESPONSE:
+ pvscsi_req->cmp.hostStatus = BTSTAT_SELTIMEO;
+ break;
+ case SCSI_HOST_RESET:
+ pvscsi_req->cmp.hostStatus = BTSTAT_BUSRESET;
+ break;
+ default:
+ pvscsi_req->cmp.hostStatus = BTSTAT_HASOFTWARE;
+ break;
+ }
+ pvscsi_req->cmp.scsiStatus = GOOD;
+ qemu_sglist_destroy(&pvscsi_req->sgl);
+ pvscsi_complete_request(s, pvscsi_req);
+}
+
static void
pvscsi_command_complete(SCSIRequest *req, size_t resid)
{
@@ -1103,6 +1141,7 @@ static const struct SCSIBusInfo pvscsi_scsi_info = {
.get_sg_list = pvscsi_get_sg_list,
.complete = pvscsi_command_complete,
.cancel = pvscsi_request_cancelled,
+ .fail = pvscsi_command_failed,
};
static void
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 5d992e6e1d..ee7876674c 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -27,7 +27,8 @@ struct SCSIRequest {
uint32_t refcount;
uint32_t tag;
uint32_t lun;
- uint32_t status;
+ int16_t status;
+ int16_t host_status;
void *hba_private;
size_t resid;
SCSICommand cmd;
@@ -123,6 +124,7 @@ struct SCSIBusInfo {
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
void *hba_private);
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
+ void (*fail)(SCSIRequest *req);
void (*complete)(SCSIRequest *req, size_t resid);
void (*cancel)(SCSIRequest *req);
void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense);
diff --git a/include/scsi/constants.h b/include/scsi/constants.h
index 2a32c08b5e..0ee29bfd7d 100644
--- a/include/scsi/constants.h
+++ b/include/scsi/constants.h
@@ -181,6 +181,9 @@
#define STATUS_MASK 0x3e
+/* QEMU only. */
+#define CHECK_HOST_STATUS 0xff
+
/*
* SENSE KEYS
*/
--
2.29.2
next prev parent reply other threads:[~2021-02-24 18:34 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-24 18:24 [PATCH 00/11] scsi-generic: error handling overhaul Paolo Bonzini
2021-02-24 18:24 ` [PATCH 01/10] scsi-disk: move scsi_handle_rw_error earlier Paolo Bonzini
2021-02-24 18:24 ` [PATCH 02/10] scsi-disk: do not complete requests early for rerror/werror=ignore Paolo Bonzini
2021-02-24 18:24 ` [PATCH 03/10] scsi: introduce scsi_sense_from_errno() Paolo Bonzini
2021-02-24 18:24 ` [PATCH 04/10] scsi-disk: pass SCSI status to scsi_handle_rw_error Paolo Bonzini
2021-02-24 18:24 ` [PATCH 05/10] scsi-disk: pass guest recoverable errors through even for rerror=stop Paolo Bonzini
2021-02-24 18:24 ` [PATCH 06/10] scsi: drop 'result' argument from command_complete callback Paolo Bonzini
2021-02-24 18:24 ` [PATCH 07/10] scsi: Rename linux-specific SG_ERR codes to generic SCSI_HOST error codes Paolo Bonzini
2021-02-24 18:24 ` [PATCH 08/10] scsi: Add mapping for generic SCSI_HOST status to sense codes Paolo Bonzini
2021-02-24 18:24 ` [PATCH 09/10] scsi: inline sg_io_sense_from_errno() into the callers Paolo Bonzini
2021-02-24 18:24 ` Paolo Bonzini [this message]
2021-02-24 19:05 ` [PATCH 00/11] scsi-generic: error handling overhaul Philippe Mathieu-Daudé
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210224182453.587731-11-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=hare@suse.de \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).