From: Paolo Bonzini <pbonzini@redhat.com>
To: Shinichiro Kawasaki <shinichiro.kawasaki@wdc.com>,
Alistair Francis <alistair23@gmail.com>
Cc: "fam@euphon.net" <fam@euphon.net>,
Alistair Francis <Alistair.Francis@wdc.com>,
"qemu-devel@nongnu.org Developers" <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] [PATCH v1 1/1] hw/scsi: Report errors and sense to guests through scsi-block
Date: Fri, 5 Jul 2019 19:08:17 +0200 [thread overview]
Message-ID: <8a5bd434-4c4c-f5ae-cae4-a23f6463a05c@redhat.com> (raw)
In-Reply-To: <BN3PR04MB22577C778C58BC5E2C8DD61FEDF50@BN3PR04MB2257.namprd04.prod.outlook.com>
[-- Attachment #1: Type: text/plain, Size: 652 bytes --]
On 05/07/19 12:31, Shinichiro Kawasaki wrote:
>> This way there's generally no need to shoehorn ASC codes into errno. I
>> still have to test my changes, but I hope to send something within a
>> couple of days.
>
> Thanks for sharing your thoughts. Now I understand your idea.
>
> I'm awaiting your patch. In case you want me to create the patch based on your
> idea, please let me know. I can afford some time next week to work on it.
I didn't have time to finish, but since I will be out for part of next
week, here is what I currently have (untested, somewhat uncompiled).
It's a bugfix so it can be included after hard freeze.
Thanks!
Paolo
[-- Attachment #2: scsi-sense.patch --]
[-- Type: text/x-patch, Size: 14051 bytes --]
From fdccbd77192ca4450f6e8900bef392fa36242200 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 5 Jul 2019 19:07:17 +0200
Subject: [PATCH 0/5] *** SUBJECT HERE ***
*** BLURB HERE ***
Paolo Bonzini (4):
scsi: explicitly list guest-recoverable sense codes
scsi: add guest-recoverable ZBC errors
iscsi: fix busy/timeout/task set full
iscsi: base all handling of check condition on scsi_sense_to_errno
Shinichiro Kawasaki (1):
scsi-disk: pass sense correctly for guest-recoverable errors
block/iscsi.c | 28 +++++++++++------------
hw/scsi/scsi-disk.c | 15 ++++++++++---
include/scsi/utils.h | 1 +
scsi/utils.c | 53 +++++++++++++++++++++++++++++++++++++++++---
4 files changed, 77 insertions(+), 20 deletions(-)
--
2.21.0
From f8a4b9cd0cd878aacbdf4ad4e7a2451c87339dab Mon Sep 17 00:00:00 2001
From: Shinichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Date: Tue, 2 Jul 2019 10:08:00 +0200
Subject: [PATCH 1/5] scsi-disk: pass sense correctly for guest-recoverable
errors
When an error was passed down to the guest because it was recoverable,
the sense length was not copied from the SG_IO data. As a result,
the guest saw the CHECK CONDITION status but not the sense data.
Signed-off-by: Shinichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/scsi/scsi-disk.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index ed7295bfd7..5d3fb3c9d5 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -62,6 +62,7 @@ typedef struct SCSIDiskClass {
DMAIOFunc *dma_readv;
DMAIOFunc *dma_writev;
bool (*need_fua_emulation)(SCSICommand *cmd);
+ void (*update_sense)(SCSIRequest *r);
} SCSIDiskClass;
typedef struct SCSIDiskReq {
@@ -438,6 +439,7 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
{
bool is_read = (r->req.cmd.mode == SCSI_XFER_FROM_DEV);
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+ SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
BlockErrorAction action = blk_get_error_action(s->qdev.conf.blk,
is_read, error);
@@ -456,6 +458,7 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
if (error == ECANCELED || error == EAGAIN || error == ENOTCONN ||
error == 0) {
/* These errors are handled by guest. */
+ sdc->update_sense(&r->req);
scsi_req_complete(&r->req, *r->status);
return true;
}
@@ -2894,6 +2897,12 @@ static int scsi_block_parse_cdb(SCSIDevice *d, SCSICommand *cmd,
}
}
+static void scsi_block_update_sense(SCSIRequest *req)
+{
+ SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
+ SCSIBlockReq *br = DO_UPCAST(SCSIBlockReq, req, r);
+ r->req.sense_len = MIN(br->io_header.sb_len_wr, sizeof(r->req.sense));
+}
#endif
static
@@ -3059,6 +3068,7 @@ static void scsi_block_class_initfn(ObjectClass *klass, void *data)
sc->parse_cdb = scsi_block_parse_cdb;
sdc->dma_readv = scsi_block_dma_readv;
sdc->dma_writev = scsi_block_dma_writev;
+ sdc->update_sense = scsi_block_update_sense;
sdc->need_fua_emulation = scsi_block_no_fua;
dc->desc = "SCSI block device passthrough";
dc->props = scsi_block_properties;
--
2.21.0
From ab60dfcd4c2bbad79d2bdfae37a88b031917ec99 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 2 Jul 2019 10:23:20 +0200
Subject: [PATCH 2/5] scsi: explicitly list guest-recoverable sense codes
It's not really possible to fit all sense codes into errno codes, especially
in such a way that sense codes can be properly categorized as either.
guest-recoverable and host-handled. Just create a new function that
checks for guest recoverable sense, then scsi_sense_buf_to_errno only
needs to be called for host handled sense codes.
---
hw/scsi/scsi-disk.c | 5 ++---
include/scsi/utils.h | 1 +
scsi/utils.c | 43 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 5d3fb3c9d5..8e95e3e38d 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -454,14 +454,13 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
* pause the host.
*/
assert(r->status && *r->status);
- error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense));
- if (error == ECANCELED || error == EAGAIN || error == ENOTCONN ||
- error == 0) {
+ 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);
return true;
}
+ error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense));
break;
case ENOMEDIUM:
scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
diff --git a/include/scsi/utils.h b/include/scsi/utils.h
index 9351b21ead..fee6212e85 100644
--- a/include/scsi/utils.h
+++ b/include/scsi/utils.h
@@ -106,6 +106,7 @@ extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED;
int scsi_sense_to_errno(int key, int asc, int ascq);
int scsi_sense_buf_to_errno(const uint8_t *sense, size_t sense_size);
+int scsi_sense_buf_is_guest_recoverable(const uint8_t *sense, size_t sense_size);
int scsi_convert_sense(uint8_t *in_buf, int in_len,
uint8_t *buf, int len, bool fixed);
diff --git a/scsi/utils.c b/scsi/utils.c
index 8738522955..3ad28face1 100644
--- a/scsi/utils.c
+++ b/scsi/utils.c
@@ -336,6 +336,38 @@ int scsi_convert_sense(uint8_t *in_buf, int in_len,
}
}
+static bool scsi_sense_is_guest_recoverable(int key, int asc, int ascq)
+{
+ switch (key) {
+ case NO_SENSE:
+ case RECOVERED_ERROR:
+ case UNIT_ATTENTION:
+ case ABORTED_COMMAND:
+ return true;
+ case NOT_READY:
+ case ILLEGAL_REQUEST:
+ case DATA_PROTECT:
+ /* Parse ASCQ */
+ break;
+ default:
+ return false;
+ }
+
+ switch ((asc << 8) | ascq) {
+ case 0x1a00: /* PARAMETER LIST LENGTH ERROR */
+ case 0x2000: /* INVALID OPERATION CODE */
+ case 0x2400: /* INVALID FIELD IN CDB */
+ case 0x2500: /* LOGICAL UNIT NOT SUPPORTED */
+ case 0x2600: /* INVALID FIELD IN PARAMETER LIST */
+
+ case 0x0401: /* NOT READY, IN PROGRESS OF BECOMING READY */
+ case 0x0402: /* NOT READY, INITIALIZING COMMAND REQUIRED */
+ return true;
+ default:
+ return false;
+ }
+}
+
int scsi_sense_to_errno(int key, int asc, int ascq)
{
switch (key) {
@@ -391,6 +423,17 @@ int scsi_sense_buf_to_errno(const uint8_t *in_buf, size_t in_len)
return scsi_sense_to_errno(sense.key, sense.asc, sense.ascq);
}
+bool scsi_sense_buf_is_guest_recoverable(const uint8_t *in_buf, size_t in_len)
+{
+ SCSISense sense;
+ if (in_len < 1) {
+ return false;
+ }
+
+ sense = scsi_parse_sense_buf(in_buf, in_len);
+ return scsi_sense_to_errno(sense.key, sense.asc, sense.ascq);
+}
+
const char *scsi_command_name(uint8_t cmd)
{
static const char *names[] = {
--
2.21.0
From eca5917fcdf3ea690ee80d6f073d3b915691a499 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 2 Jul 2019 10:01:03 +0200
Subject: [PATCH 3/5] scsi: add guest-recoverable ZBC errors
When I ran basic operations to the zoned storage from the guest via
scsi-block the following ASCs are reported for write or read commands
due to unexpected zone status or write pointer status:
21h 04h: UNALIGNED WRITE COMMAND
21h 05h: WRITE BOUNDARY VIOLATION
21h 06h: ATTEMPT TO READ INVALID DATA
55h 0Eh: INSUFFICIENT ZONE RESOURCES
Reporting these ASCs to the guest, the user applications can handle
them to manage zone/write pointer status, or help the user application
developers to understand the failure reason and fix bugs.
Reported-by: Shinichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
scsi/utils.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/scsi/utils.c b/scsi/utils.c
index 3ad28face1..53274f62d7 100644
--- a/scsi/utils.c
+++ b/scsi/utils.c
@@ -360,6 +360,11 @@ static bool scsi_sense_is_guest_recoverable(int key, int asc, int ascq)
case 0x2500: /* LOGICAL UNIT NOT SUPPORTED */
case 0x2600: /* INVALID FIELD IN PARAMETER LIST */
+ case 0x2104: /* UNALIGNED WRITE COMMAND */
+ case 0x2105: /* WRITE BOUNDARY VIOLATION */
+ case 0x2106: /* ATTEMPT TO READ INVALID DATA */
+ case 0x550e: /* INSUFFICIENT ZONE RESOURCES */
+
case 0x0401: /* NOT READY, IN PROGRESS OF BECOMING READY */
case 0x0402: /* NOT READY, INITIALIZING COMMAND REQUIRED */
return true;
--
2.21.0
From 594c17e8f6d617d5f234e1d3701cfc54e6804d1a Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 2 Jul 2019 10:45:54 +0200
Subject: [PATCH 4/5] iscsi: fix busy/timeout/task set full
In this case, do_retry was set without calling aio_co_wake, thus never
waking up the coroutine.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
block/iscsi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/iscsi.c b/block/iscsi.c
index 267f160bf6..6e238bf0ad 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -272,7 +272,7 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
timer_mod(&iTask->retry_timer,
qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + retry_time);
iTask->do_retry = 1;
- return;
+ goto out;
}
}
iTask->err_code = iscsi_translate_sense(&task->sense);
--
2.21.0
From fdccbd77192ca4450f6e8900bef392fa36242200 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 2 Jul 2019 11:40:41 +0200
Subject: [PATCH 5/5] iscsi: base all handling of check condition on
scsi_sense_to_errno
Now that scsi-disk is not using scsi_sense_to_errno to separate guest-recoverable
sense codes, we can modify it to simplify iscsi's own sense handling.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
block/iscsi.c | 28 ++++++++++++++--------------
scsi/utils.c | 5 ++---
2 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/block/iscsi.c b/block/iscsi.c
index 6e238bf0ad..5817967205 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -225,9 +225,9 @@ static inline unsigned exp_random(double mean)
static int iscsi_translate_sense(struct scsi_sense *sense)
{
- return - scsi_sense_to_errno(sense->key,
- (sense->ascq & 0xFF00) >> 8,
- sense->ascq & 0xFF);
+ return scsi_sense_to_errno(sense->key,
+ (sense->ascq & 0xFF00) >> 8,
+ sense->ascq & 0xFF);
}
/* Called (via iscsi_service) with QemuMutex held. */
@@ -244,13 +244,6 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
if (status != SCSI_STATUS_GOOD) {
if (iTask->retries++ < ISCSI_CMD_RETRIES) {
- if (status == SCSI_STATUS_CHECK_CONDITION
- && task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
- error_report("iSCSI CheckCondition: %s",
- iscsi_get_error(iscsi));
- iTask->do_retry = 1;
- goto out;
- }
if (status == SCSI_STATUS_BUSY ||
status == SCSI_STATUS_TIMEOUT ||
status == SCSI_STATUS_TASK_SET_FULL) {
@@ -272,11 +265,18 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
timer_mod(&iTask->retry_timer,
qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + retry_time);
iTask->do_retry = 1;
- goto out;
+ }
+ } else if (status == SCSI_STATUS_CHECK_CONDITION) {
+ int error = iscsi_translate_sense(&task->sense);
+ if (error == EAGAIN) {
+ error_report("iSCSI CheckCondition: %s",
+ iscsi_get_error(iscsi));
+ iTask->do_retry = 1;
+ } else {
+ iTask->err_code = -error;
+ iTask->err_str = g_strdup(iscsi_get_error(iscsi));
}
}
- iTask->err_code = iscsi_translate_sense(&task->sense);
- iTask->err_str = g_strdup(iscsi_get_error(iscsi));
}
out:
@@ -974,7 +974,7 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
if (status < 0) {
error_report("Failed to ioctl(SG_IO) to iSCSI lun. %s",
iscsi_get_error(iscsi));
- acb->status = iscsi_translate_sense(&acb->task->sense);
+ acb->status = -iscsi_translate_sense(&acb->task->sense);
}
acb->ioh->driver_status = 0;
diff --git a/scsi/utils.c b/scsi/utils.c
index 53274f62d7..7f332ebf1f 100644
--- a/scsi/utils.c
+++ b/scsi/utils.c
@@ -379,8 +379,7 @@ int scsi_sense_to_errno(int key, int asc, int ascq)
case NO_SENSE:
case RECOVERED_ERROR:
case UNIT_ATTENTION:
- /* These sense keys are not errors */
- return 0;
+ return EAGAIN;
case ABORTED_COMMAND: /* COMMAND ABORTED */
return ECANCELED;
case NOT_READY:
@@ -409,7 +408,7 @@ int scsi_sense_to_errno(int key, int asc, int ascq)
case 0x2700: /* WRITE PROTECTED */
return EACCES;
case 0x0401: /* NOT READY, IN PROGRESS OF BECOMING READY */
- return EAGAIN;
+ return EINPROGRESS;
case 0x0402: /* NOT READY, INITIALIZING COMMAND REQUIRED */
return ENOTCONN;
default:
--
2.21.0
next prev parent reply other threads:[~2019-07-05 17:12 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-26 22:46 [Qemu-devel] [PATCH v1 1/1] hw/scsi: Report errors and sense to guests through scsi-block Alistair Francis
2019-06-27 9:01 ` Paolo Bonzini
2019-06-28 21:57 ` Alistair Francis
2019-06-28 22:14 ` Paolo Bonzini
2019-06-28 22:18 ` Alistair Francis
2019-07-01 10:14 ` Shinichiro Kawasaki
2019-07-01 11:56 ` Paolo Bonzini
2019-07-02 6:44 ` Shinichiro Kawasaki
2019-07-02 10:22 ` Paolo Bonzini
2019-07-05 10:31 ` Shinichiro Kawasaki
2019-07-05 17:08 ` Paolo Bonzini [this message]
2019-07-09 8:27 ` Shinichiro Kawasaki
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=8a5bd434-4c4c-f5ae-cae4-a23f6463a05c@redhat.com \
--to=pbonzini@redhat.com \
--cc=Alistair.Francis@wdc.com \
--cc=alistair23@gmail.com \
--cc=fam@euphon.net \
--cc=qemu-devel@nongnu.org \
--cc=shinichiro.kawasaki@wdc.com \
/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).