182 lines
6.4 KiB
Diff
182 lines
6.4 KiB
Diff
|
From 38a29a168f4b377eb6381469af16887e12ebfa3d Mon Sep 17 00:00:00 2001
|
||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||
|
Date: Mon, 8 Mar 2021 10:49:00 -0500
|
||
|
Subject: [PATCH 03/15] scsi: introduce scsi_sense_from_errno()
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||
|
Message-id: <20210308104902.149906-4-pbonzini@redhat.com>
|
||
|
Patchwork-id: 101308
|
||
|
O-Subject: [RHEL-AV-8.4.0 qemu-kvm PATCH 3/5] scsi: introduce scsi_sense_from_errno()
|
||
|
Bugzilla: 1927530
|
||
|
RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||
|
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||
|
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||
|
|
||
|
The new function is an extension of the switch statement in scsi-disk.c
|
||
|
which also includes the errno cases only found in sg_io_sense_from_errno.
|
||
|
This allows us to consolidate the errno handling.
|
||
|
|
||
|
Extracted from a patch by Hannes Reinecke <hare@suse.de>.
|
||
|
|
||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||
|
(cherry picked from commit d7a84021db8eeddcd5d24ab591a1434763caff6c)
|
||
|
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
||
|
---
|
||
|
hw/scsi/scsi-disk.c | 45 +++++++-------------------------------
|
||
|
include/scsi/utils.h | 2 ++
|
||
|
scsi/utils.c | 51 +++++++++++++++++++++++++++++++++++---------
|
||
|
3 files changed, 51 insertions(+), 47 deletions(-)
|
||
|
|
||
|
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
|
||
|
index e8de15f549..7393f33ee2 100644
|
||
|
--- a/hw/scsi/scsi-disk.c
|
||
|
+++ b/hw/scsi/scsi-disk.c
|
||
|
@@ -193,13 +193,13 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
|
||
|
SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
|
||
|
BlockErrorAction action = blk_get_error_action(s->qdev.conf.blk,
|
||
|
is_read, error);
|
||
|
+ SCSISense sense;
|
||
|
|
||
|
if (action == BLOCK_ERROR_ACTION_REPORT) {
|
||
|
if (acct_failed) {
|
||
|
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
|
||
|
}
|
||
|
- switch (error) {
|
||
|
- case 0:
|
||
|
+ if (error == 0) {
|
||
|
/* A passthrough command has run and has produced sense data; check
|
||
|
* whether the error has to be handled by the guest or should rather
|
||
|
* pause the host.
|
||
|
@@ -212,41 +212,12 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
|
||
|
return true;
|
||
|
}
|
||
|
error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense));
|
||
|
- break;
|
||
|
-#ifdef CONFIG_LINUX
|
||
|
- /* These errno mapping are specific to Linux. For more information:
|
||
|
- * - scsi_decide_disposition in drivers/scsi/scsi_error.c
|
||
|
- * - scsi_result_to_blk_status in drivers/scsi/scsi_lib.c
|
||
|
- * - blk_errors[] in block/blk-core.c
|
||
|
- */
|
||
|
- case EBADE:
|
||
|
- /* DID_NEXUS_FAILURE -> BLK_STS_NEXUS. */
|
||
|
- scsi_req_complete(&r->req, RESERVATION_CONFLICT);
|
||
|
- break;
|
||
|
- case ENODATA:
|
||
|
- /* DID_MEDIUM_ERROR -> BLK_STS_MEDIUM. */
|
||
|
- scsi_check_condition(r, SENSE_CODE(READ_ERROR));
|
||
|
- break;
|
||
|
- case EREMOTEIO:
|
||
|
- /* DID_TARGET_FAILURE -> BLK_STS_TARGET. */
|
||
|
- scsi_req_complete(&r->req, HARDWARE_ERROR);
|
||
|
- break;
|
||
|
-#endif
|
||
|
- case ENOMEDIUM:
|
||
|
- scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
|
||
|
- break;
|
||
|
- case ENOMEM:
|
||
|
- scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE));
|
||
|
- break;
|
||
|
- case EINVAL:
|
||
|
- scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
|
||
|
- break;
|
||
|
- case ENOSPC:
|
||
|
- scsi_check_condition(r, SENSE_CODE(SPACE_ALLOC_FAILED));
|
||
|
- break;
|
||
|
- default:
|
||
|
- scsi_check_condition(r, SENSE_CODE(IO_ERROR));
|
||
|
- break;
|
||
|
+ } else {
|
||
|
+ int status = scsi_sense_from_errno(error, &sense);
|
||
|
+ if (status == CHECK_CONDITION) {
|
||
|
+ scsi_req_build_sense(&r->req, sense);
|
||
|
+ }
|
||
|
+ scsi_req_complete(&r->req, status);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
diff --git a/include/scsi/utils.h b/include/scsi/utils.h
|
||
|
index fbc5588279..878434a8f5 100644
|
||
|
--- a/include/scsi/utils.h
|
||
|
+++ b/include/scsi/utils.h
|
||
|
@@ -133,4 +133,6 @@ 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);
|
||
|
+
|
||
|
#endif
|
||
|
diff --git a/scsi/utils.c b/scsi/utils.c
|
||
|
index b37c283014..c93458b80e 100644
|
||
|
--- a/scsi/utils.c
|
||
|
+++ b/scsi/utils.c
|
||
|
@@ -560,21 +560,52 @@ const char *scsi_command_name(uint8_t cmd)
|
||
|
return names[cmd];
|
||
|
}
|
||
|
|
||
|
+int scsi_sense_from_errno(int errno_value, SCSISense *sense)
|
||
|
+{
|
||
|
+ switch (errno_value) {
|
||
|
+ case 0:
|
||
|
+ return GOOD;
|
||
|
+ case EDOM:
|
||
|
+ return TASK_SET_FULL;
|
||
|
+#ifdef CONFIG_LINUX
|
||
|
+ /* These errno mapping are specific to Linux. For more information:
|
||
|
+ * - scsi_decide_disposition in drivers/scsi/scsi_error.c
|
||
|
+ * - scsi_result_to_blk_status in drivers/scsi/scsi_lib.c
|
||
|
+ * - blk_errors[] in block/blk-core.c
|
||
|
+ */
|
||
|
+ case EBADE:
|
||
|
+ return RESERVATION_CONFLICT;
|
||
|
+ case ENODATA:
|
||
|
+ *sense = SENSE_CODE(READ_ERROR);
|
||
|
+ return CHECK_CONDITION;
|
||
|
+ case EREMOTEIO:
|
||
|
+ *sense = SENSE_CODE(LUN_COMM_FAILURE);
|
||
|
+ return CHECK_CONDITION;
|
||
|
+#endif
|
||
|
+ case ENOMEDIUM:
|
||
|
+ *sense = SENSE_CODE(NO_MEDIUM);
|
||
|
+ return CHECK_CONDITION;
|
||
|
+ case ENOMEM:
|
||
|
+ *sense = SENSE_CODE(TARGET_FAILURE);
|
||
|
+ return CHECK_CONDITION;
|
||
|
+ case EINVAL:
|
||
|
+ *sense = SENSE_CODE(INVALID_FIELD);
|
||
|
+ return CHECK_CONDITION;
|
||
|
+ case ENOSPC:
|
||
|
+ *sense = SENSE_CODE(SPACE_ALLOC_FAILED);
|
||
|
+ return CHECK_CONDITION;
|
||
|
+ default:
|
||
|
+ *sense = SENSE_CODE(IO_ERROR);
|
||
|
+ return CHECK_CONDITION;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
#ifdef CONFIG_LINUX
|
||
|
int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
|
||
|
SCSISense *sense)
|
||
|
{
|
||
|
if (errno_value != 0) {
|
||
|
- switch (errno_value) {
|
||
|
- case EDOM:
|
||
|
- return TASK_SET_FULL;
|
||
|
- case ENOMEM:
|
||
|
- *sense = SENSE_CODE(TARGET_FAILURE);
|
||
|
- return CHECK_CONDITION;
|
||
|
- default:
|
||
|
- *sense = SENSE_CODE(IO_ERROR);
|
||
|
- return CHECK_CONDITION;
|
||
|
- }
|
||
|
+ return scsi_sense_from_errno(errno_value, sense);
|
||
|
} else {
|
||
|
if (io_hdr->host_status == SG_ERR_DID_NO_CONNECT ||
|
||
|
io_hdr->host_status == SG_ERR_DID_BUS_BUSY ||
|
||
|
--
|
||
|
2.27.0
|
||
|
|