- hw/nvme: Remove redundant dma_blk_write - tests/avocado/machine_s390_ccw_virtio: Adapt test to new default resolution - edid: set default resolution to 1280x800 (WXGA) - iotests/308: Fix for CAP_DAC_OVERRIDE - hvf: remove unused but set variable - vvfat: Fix vvfat_write() for writes before the root directory - hw/misc/nrf51_rng: Don't use BIT_MASK() when we mean BIT() - hw/pci: Remove unused pci_irq_pulse() method - ui/gtk: fix leaks found wtih fuzzing - target/i386: fix size of EBP writeback in gen_enter() - tests/qtest/fuzz: fix memleak in qos_fuzz.c - hw/core/loader: gunzip(): fix memory leak on error path - migration: fix a typo - scsi: fetch unit attention when creating the request - raw-format: Fix error message for invalid offset/size - tcg: Reset data_gen_ptr correctly - Fix calculation of minimum in colo_compare_tcp - hw/intc: Don't clear pending bits on IRQ lowering - target/arm: Drop user-only special case in sve_stN_r - usb-hub: Fix handling port power control messages - target/ppc: Set ctx->opcode for decode_insn32() - linux-user: Add proper strace format strings for getdents()/getdents64() - linux-user: Fix TARGET_PROT_SEM for XTENSA - linux-user/hppa: Set TASK_UNMAPPED_BASE to 0xfa000000 for hppa arch - linux-user/hppa: Dump IIR on register dump - tests: Fix typo in check-help output - qdev-core.h: Fix wrongly named reference to TYPE_SPLIT_IRQ - hw/scsi/megasas: Simplify using the ldst API - gqa-win: get_pci_info: Clean dev_info if handle is valid - target/ppc: Fix 7448 support - vvfat: Fix size of temporary qcow file - docs: Correct 'vhost-user-blk' spelling - jackaudio: use ifdefs to hide unavailable functions - simplebench: Fix Python syntax error (reported by LGTM) - python: update type hints for mypy 0.930 - Python/aqmp: fix type definitions for mypy 0.920 - tcg: Allow top bit of SIMD_DATA_BITS to be set in simd_desc() - hw/ppc/e500: Prefer QOM cast - hw/ppc/e500: Remove unused "irqs" parameter - hw/ppc/e500: Add missing device tree properties to i2c controller node - linux-user: Show timespec on strace for futex() - linux-user: Add strace for clock_nanosleep() - linux-user: Fix strace of chmod() if mode == 0 - linux-user: Log failing executable in EXCP_DUMP() - linux-user: Add pidfd_open(), pidfd_send_signal() and pidfd_getfd() syscalls Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com> (cherry picked from commit 87ebac5b5cfb97ddb7ac2af097703758fb0751c4)
125 lines
4.5 KiB
Diff
125 lines
4.5 KiB
Diff
From 73a7cffceeae9561d75e40e04e7ae3d52e1ef4a5 Mon Sep 17 00:00:00 2001
|
|
From: Stefano Garzarella <sgarzare@redhat.com>
|
|
Date: Wed, 12 Jul 2023 15:43:50 +0200
|
|
Subject: [PATCH] scsi: fetch unit attention when creating the request
|
|
|
|
Commit 1880ad4f4e ("virtio-scsi: Batched prepare for cmd reqs") split
|
|
calls to scsi_req_new() and scsi_req_enqueue() in the virtio-scsi device.
|
|
No ill effects were observed until commit 8cc5583abe ("virtio-scsi: Send
|
|
"REPORTED LUNS CHANGED" sense data upon disk hotplug events") added a
|
|
unit attention that was easy to trigger with device hotplug and
|
|
hot-unplug.
|
|
|
|
Because the two calls were separated, all requests in the batch were
|
|
prepared calling scsi_req_new() to report a sense. The first one
|
|
submitted would report the right sense and reset it to NO_SENSE, while
|
|
the others reported CHECK_CONDITION with no sense data. This caused
|
|
SCSI errors in Linux.
|
|
|
|
To solve this issue, let's fetch the unit attention as early as possible
|
|
when we prepare the request, so that only the first request in the batch
|
|
will use the unit attention SCSIReqOps and the others will not report
|
|
CHECK CONDITION.
|
|
|
|
Fixes: 1880ad4f4e ("virtio-scsi: Batched prepare for cmd reqs")
|
|
Fixes: 8cc5583abe ("virtio-scsi: Send "REPORTED LUNS CHANGED" sense data upon disk hotplug events")
|
|
Reported-by: Thomas Huth <thuth@redhat.com>
|
|
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2176702
|
|
Co-developed-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
Message-ID: <20230712134352.118655-2-sgarzare@redhat.com>
|
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
(cherry picked from commit 9472083e642bfb9bc836b38662baddd9bc964ebc)
|
|
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
|
|
---
|
|
hw/scsi/scsi-bus.c | 36 +++++++++++++++++++++++++++++++++---
|
|
include/hw/scsi/scsi.h | 1 +
|
|
2 files changed, 34 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
|
|
index 89c4693cc2..613ad41de9 100644
|
|
--- a/hw/scsi/scsi-bus.c
|
|
+++ b/hw/scsi/scsi-bus.c
|
|
@@ -419,19 +419,35 @@ static const struct SCSIReqOps reqops_invalid_opcode = {
|
|
|
|
/* SCSIReqOps implementation for unit attention conditions. */
|
|
|
|
-static int32_t scsi_unit_attention(SCSIRequest *req, uint8_t *buf)
|
|
+static void scsi_fetch_unit_attention_sense(SCSIRequest *req)
|
|
{
|
|
+ SCSISense *ua = NULL;
|
|
+
|
|
if (req->dev->unit_attention.key == UNIT_ATTENTION) {
|
|
- scsi_req_build_sense(req, req->dev->unit_attention);
|
|
+ ua = &req->dev->unit_attention;
|
|
} else if (req->bus->unit_attention.key == UNIT_ATTENTION) {
|
|
- scsi_req_build_sense(req, req->bus->unit_attention);
|
|
+ ua = &req->bus->unit_attention;
|
|
}
|
|
+
|
|
+ /*
|
|
+ * Fetch the unit attention sense immediately so that another
|
|
+ * scsi_req_new does not use reqops_unit_attention.
|
|
+ */
|
|
+ if (ua) {
|
|
+ scsi_req_build_sense(req, *ua);
|
|
+ *ua = SENSE_CODE(NO_SENSE);
|
|
+ }
|
|
+}
|
|
+
|
|
+static int32_t scsi_unit_attention(SCSIRequest *req, uint8_t *buf)
|
|
+{
|
|
scsi_req_complete(req, CHECK_CONDITION);
|
|
return 0;
|
|
}
|
|
|
|
static const struct SCSIReqOps reqops_unit_attention = {
|
|
.size = sizeof(SCSIRequest),
|
|
+ .init_req = scsi_fetch_unit_attention_sense,
|
|
.send_command = scsi_unit_attention
|
|
};
|
|
|
|
@@ -705,6 +721,11 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
|
|
object_ref(OBJECT(d));
|
|
object_ref(OBJECT(qbus->parent));
|
|
notifier_list_init(&req->cancel_notifiers);
|
|
+
|
|
+ if (reqops->init_req) {
|
|
+ reqops->init_req(req);
|
|
+ }
|
|
+
|
|
trace_scsi_req_alloc(req->dev->id, req->lun, req->tag);
|
|
return req;
|
|
}
|
|
@@ -798,6 +819,15 @@ uint8_t *scsi_req_get_buf(SCSIRequest *req)
|
|
static void scsi_clear_unit_attention(SCSIRequest *req)
|
|
{
|
|
SCSISense *ua;
|
|
+
|
|
+ /*
|
|
+ * scsi_fetch_unit_attention_sense() already cleaned the unit attention
|
|
+ * in this case.
|
|
+ */
|
|
+ if (req->ops == &reqops_unit_attention) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
if (req->dev->unit_attention.key != UNIT_ATTENTION &&
|
|
req->bus->unit_attention.key != UNIT_ATTENTION) {
|
|
return;
|
|
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
|
|
index e5d90cd9dc..80c9eb00e4 100644
|
|
--- a/include/hw/scsi/scsi.h
|
|
+++ b/include/hw/scsi/scsi.h
|
|
@@ -108,6 +108,7 @@ int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
|
|
/* scsi-bus.c */
|
|
struct SCSIReqOps {
|
|
size_t size;
|
|
+ void (*init_req)(SCSIRequest *req);
|
|
void (*free_req)(SCSIRequest *req);
|
|
int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
|
|
void (*read_data)(SCSIRequest *req);
|
|
--
|
|
2.41.0.windows.1
|
|
|