File scsi-make-io_timeout-settable.patch of Package qemu.30222
From: Hannes Reinecke <hare@suse.de>
Date: Thu, 29 Oct 2020 12:41:21 +0100
Subject: scsi: make io_timeout settable
References: bsc#1178049,bsc#1194938
Add an 'io_timeout' parameter for SCSIDevice to allow
SG_IO ioctls to pass in a timeout, avoiding infinite
guest stalls if the host needs to abort a command.
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Lin Ma <lma@suse.com>
---
hw/scsi/scsi-disk.c | 7 +++++--
hw/scsi/scsi-generic.c | 15 +++++++++------
include/hw/scsi/scsi.h | 3 ++-
3 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index e2eb7f1b3967fecc70d05de84ace..9057fc26b37e18c7344018e86ef3 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -51,6 +51,7 @@
#define DEFAULT_DISCARD_GRANULARITY (4 * KiB)
#define DEFAULT_MAX_UNMAP_SIZE (1 * GiB)
+#define DEFAULT_IO_TIMEOUT UINT_MAX /* Infinity */
#define DEFAULT_MAX_IO_SIZE INT_MAX /* 2 GB - 1 block */
#define TYPE_SCSI_DISK_BASE "scsi-disk-base"
@@ -2629,7 +2630,7 @@ static int get_device_type(SCSIDiskState *s)
cmd[4] = sizeof(buf);
ret = scsi_SG_IO_FROM_DEV(s->qdev.conf.blk, cmd, sizeof(cmd),
- buf, sizeof(buf));
+ buf, sizeof(buf), s->qdev.io_timeout);
if (ret < 0) {
return -1;
}
@@ -2790,7 +2791,7 @@ static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req,
/* The rest is as in scsi-generic.c. */
io_header->mx_sb_len = sizeof(r->req.sense);
io_header->sbp = r->req.sense;
- io_header->timeout = UINT_MAX;
+ io_header->timeout = s->qdev.io_timeout;
io_header->usr_ptr = r;
io_header->flags |= SG_FLAG_DIRECT_IO;
@@ -3108,6 +3109,8 @@ static Property scsi_block_properties[] = {
DEFAULT_MAX_IO_SIZE),
DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version,
-1),
+ DEFINE_PROP_UINT32("io_timeout", SCSIDiskState, qdev.io_timeout,
+ DEFAULT_IO_TIMEOUT),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
index bdc01b2ef9e5d7555b60cdbfb078..4d106a6885e2361286b4dfa3292f 100644
--- a/hw/scsi/scsi-generic.c
+++ b/hw/scsi/scsi-generic.c
@@ -114,6 +114,8 @@ static int execute_command(BlockBackend *blk,
SCSIGenericReq *r, int direction,
BlockCompletionFunc *complete)
{
+ SCSIDevice *s = r->req.dev;
+
r->io_header.interface_id = 'S';
r->io_header.dxfer_direction = direction;
r->io_header.dxferp = r->buf;
@@ -122,7 +124,7 @@ static int execute_command(BlockBackend *blk,
r->io_header.cmd_len = r->req.cmd.len;
r->io_header.mx_sb_len = sizeof(r->req.sense);
r->io_header.sbp = r->req.sense;
- r->io_header.timeout = MAX_UINT;
+ r->io_header.timeout = s->io_timeout;
r->io_header.usr_ptr = r;
r->io_header.flags |= SG_FLAG_DIRECT_IO;
@@ -507,7 +509,7 @@ static int read_naa_id(const uint8_t *p, uint64_t *p_wwn)
}
int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
- uint8_t *buf, uint8_t buf_size)
+ uint8_t *buf, uint8_t buf_size, uint32_t timeout)
{
sg_io_hdr_t io_header;
uint8_t sensebuf[8];
@@ -522,7 +524,7 @@ int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
io_header.cmd_len = cmd_size;
io_header.mx_sb_len = sizeof(sensebuf);
io_header.sbp = sensebuf;
- io_header.timeout = 6000; /* XXX */
+ io_header.timeout = timeout;
ret = blk_ioctl(blk, SG_IO, &io_header);
if (ret < 0 || io_header.driver_status || io_header.host_status) {
@@ -552,7 +554,7 @@ static void scsi_generic_set_vpd_bl_emulation(SCSIDevice *s)
cmd[4] = sizeof(buf);
ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd),
- buf, sizeof(buf));
+ buf, sizeof(buf), s->io_timeout);
if (ret < 0) {
/*
* Do not assume anything if we can't retrieve the
@@ -588,7 +590,7 @@ static void scsi_generic_read_device_identification(SCSIDevice *s)
cmd[4] = sizeof(buf);
ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd),
- buf, sizeof(buf));
+ buf, sizeof(buf), s->io_timeout);
if (ret < 0) {
return;
}
@@ -639,7 +641,7 @@ static int get_stream_blocksize(BlockBackend *blk)
cmd[0] = MODE_SENSE;
cmd[4] = sizeof(buf);
- ret = scsi_SG_IO_FROM_DEV(blk, cmd, sizeof(cmd), buf, sizeof(buf));
+ ret = scsi_SG_IO_FROM_DEV(blk, cmd, sizeof(cmd), buf, sizeof(buf), 60);
if (ret < 0) {
return -1;
}
@@ -729,6 +731,7 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
/* Only used by scsi-block, but initialize it nevertheless to be clean. */
s->default_scsi_version = -1;
+ s->io_timeout = 30000;
scsi_generic_read_device_inquiry(s);
}
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 09fa5c9d2a03f35f876e83f21373..b3ad910a85b656917284b36ab915 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -84,6 +84,7 @@ struct SCSIDevice
uint64_t port_wwn;
int scsi_version;
int default_scsi_version;
+ uint32_t io_timeout;
bool needs_vpd_bl_emulation;
bool hba_supports_iothread;
};
@@ -188,7 +189,7 @@ void scsi_device_unit_attention_reported(SCSIDevice *dev);
void scsi_generic_read_device_inquiry(SCSIDevice *dev);
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
- uint8_t *buf, uint8_t buf_size);
+ uint8_t *buf, uint8_t buf_size, uint32_t timeout);
SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int target, int lun);