|
|
1072c8 |
From 2903ab6d961b2165f3cbfb786cd3be59a407a6b4 Mon Sep 17 00:00:00 2001
|
|
|
1072c8 |
From: Hannes Reinecke <hare@suse.de>
|
|
|
1072c8 |
Date: Mon, 16 Nov 2020 19:31:13 +0100
|
|
|
1072c8 |
Subject: [PATCH] scsi: make io_timeout configurable
|
|
|
1072c8 |
|
|
|
1072c8 |
RH-Author: Paolo Bonzini <None>
|
|
|
1072c8 |
RH-MergeRequest: 40: scsi: make io_timeout configurable
|
|
|
1072c8 |
RH-Commit: [1/1] 147c4b7bac867c708c1905e98c4f9329ab4ef838
|
|
|
1072c8 |
RH-Bugzilla: 1994041
|
|
|
1072c8 |
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
|
|
|
1072c8 |
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
|
|
1072c8 |
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
1072c8 |
|
|
|
1072c8 |
The current code sets an infinite timeout on SG_IO requests,
|
|
|
1072c8 |
causing the guest to stall if the host experiences a frame
|
|
|
1072c8 |
loss.
|
|
|
1072c8 |
This patch adds an 'io_timeout' parameter for SCSIDevice to
|
|
|
1072c8 |
make the SG_IO timeout configurable, and also shortens the
|
|
|
1072c8 |
default timeout to 30 seconds to avoid infinite stalls.
|
|
|
1072c8 |
|
|
|
1072c8 |
Signed-off-by: Hannes Reinecke <hare@suse.de>
|
|
|
1072c8 |
Message-Id: <20201116183114.55703-3-hare@suse.de>
|
|
|
1072c8 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
1072c8 |
(cherry picked from commit c9b6609b69facad0cc5425d4fa7934c33d7f2e91)
|
|
|
1072c8 |
---
|
|
|
1072c8 |
hw/scsi/scsi-disk.c | 6 ++++--
|
|
|
1072c8 |
hw/scsi/scsi-generic.c | 17 +++++++++++------
|
|
|
1072c8 |
include/hw/scsi/scsi.h | 4 +++-
|
|
|
1072c8 |
3 files changed, 18 insertions(+), 9 deletions(-)
|
|
|
1072c8 |
|
|
|
1072c8 |
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
|
|
|
1072c8 |
index e44c61eeb4..5cb5fd35bd 100644
|
|
|
1072c8 |
--- a/hw/scsi/scsi-disk.c
|
|
|
1072c8 |
+++ b/hw/scsi/scsi-disk.c
|
|
|
1072c8 |
@@ -2610,7 +2610,7 @@ static int get_device_type(SCSIDiskState *s)
|
|
|
1072c8 |
cmd[4] = sizeof(buf);
|
|
|
1072c8 |
|
|
|
1072c8 |
ret = scsi_SG_IO_FROM_DEV(s->qdev.conf.blk, cmd, sizeof(cmd),
|
|
|
1072c8 |
- buf, sizeof(buf));
|
|
|
1072c8 |
+ buf, sizeof(buf), s->qdev.io_timeout);
|
|
|
1072c8 |
if (ret < 0) {
|
|
|
1072c8 |
return -1;
|
|
|
1072c8 |
}
|
|
|
1072c8 |
@@ -2771,7 +2771,7 @@ static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req,
|
|
|
1072c8 |
/* The rest is as in scsi-generic.c. */
|
|
|
1072c8 |
io_header->mx_sb_len = sizeof(r->req.sense);
|
|
|
1072c8 |
io_header->sbp = r->req.sense;
|
|
|
1072c8 |
- io_header->timeout = UINT_MAX;
|
|
|
1072c8 |
+ io_header->timeout = s->qdev.io_timeout * 1000;
|
|
|
1072c8 |
io_header->usr_ptr = r;
|
|
|
1072c8 |
io_header->flags |= SG_FLAG_DIRECT_IO;
|
|
|
1072c8 |
|
|
|
1072c8 |
@@ -3089,6 +3089,8 @@ static Property scsi_block_properties[] = {
|
|
|
1072c8 |
DEFAULT_MAX_IO_SIZE),
|
|
|
1072c8 |
DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version,
|
|
|
1072c8 |
-1),
|
|
|
1072c8 |
+ DEFINE_PROP_UINT32("io_timeout", SCSIDiskState, qdev.io_timeout,
|
|
|
1072c8 |
+ DEFAULT_IO_TIMEOUT),
|
|
|
1072c8 |
DEFINE_PROP_END_OF_LIST(),
|
|
|
1072c8 |
};
|
|
|
1072c8 |
|
|
|
1072c8 |
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
|
|
|
1072c8 |
index e7798ebcd0..3a383fe4d6 100644
|
|
|
1072c8 |
--- a/hw/scsi/scsi-generic.c
|
|
|
1072c8 |
+++ b/hw/scsi/scsi-generic.c
|
|
|
1072c8 |
@@ -114,6 +114,8 @@ static int execute_command(BlockBackend *blk,
|
|
|
1072c8 |
SCSIGenericReq *r, int direction,
|
|
|
1072c8 |
BlockCompletionFunc *complete)
|
|
|
1072c8 |
{
|
|
|
1072c8 |
+ SCSIDevice *s = r->req.dev;
|
|
|
1072c8 |
+
|
|
|
1072c8 |
r->io_header.interface_id = 'S';
|
|
|
1072c8 |
r->io_header.dxfer_direction = direction;
|
|
|
1072c8 |
r->io_header.dxferp = r->buf;
|
|
|
1072c8 |
@@ -122,7 +124,7 @@ static int execute_command(BlockBackend *blk,
|
|
|
1072c8 |
r->io_header.cmd_len = r->req.cmd.len;
|
|
|
1072c8 |
r->io_header.mx_sb_len = sizeof(r->req.sense);
|
|
|
1072c8 |
r->io_header.sbp = r->req.sense;
|
|
|
1072c8 |
- r->io_header.timeout = MAX_UINT;
|
|
|
1072c8 |
+ r->io_header.timeout = s->io_timeout * 1000;
|
|
|
1072c8 |
r->io_header.usr_ptr = r;
|
|
|
1072c8 |
r->io_header.flags |= SG_FLAG_DIRECT_IO;
|
|
|
1072c8 |
|
|
|
1072c8 |
@@ -503,7 +505,7 @@ static int read_naa_id(const uint8_t *p, uint64_t *p_wwn)
|
|
|
1072c8 |
}
|
|
|
1072c8 |
|
|
|
1072c8 |
int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
|
|
|
1072c8 |
- uint8_t *buf, uint8_t buf_size)
|
|
|
1072c8 |
+ uint8_t *buf, uint8_t buf_size, uint32_t timeout)
|
|
|
1072c8 |
{
|
|
|
1072c8 |
sg_io_hdr_t io_header;
|
|
|
1072c8 |
uint8_t sensebuf[8];
|
|
|
1072c8 |
@@ -518,7 +520,7 @@ int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
|
|
|
1072c8 |
io_header.cmd_len = cmd_size;
|
|
|
1072c8 |
io_header.mx_sb_len = sizeof(sensebuf);
|
|
|
1072c8 |
io_header.sbp = sensebuf;
|
|
|
1072c8 |
- io_header.timeout = 6000; /* XXX */
|
|
|
1072c8 |
+ io_header.timeout = timeout * 1000;
|
|
|
1072c8 |
|
|
|
1072c8 |
ret = blk_ioctl(blk, SG_IO, &io_header);
|
|
|
1072c8 |
if (ret < 0 || io_header.driver_status || io_header.host_status) {
|
|
|
1072c8 |
@@ -548,7 +550,7 @@ static void scsi_generic_set_vpd_bl_emulation(SCSIDevice *s)
|
|
|
1072c8 |
cmd[4] = sizeof(buf);
|
|
|
1072c8 |
|
|
|
1072c8 |
ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd),
|
|
|
1072c8 |
- buf, sizeof(buf));
|
|
|
1072c8 |
+ buf, sizeof(buf), s->io_timeout);
|
|
|
1072c8 |
if (ret < 0) {
|
|
|
1072c8 |
/*
|
|
|
1072c8 |
* Do not assume anything if we can't retrieve the
|
|
|
1072c8 |
@@ -584,7 +586,7 @@ static void scsi_generic_read_device_identification(SCSIDevice *s)
|
|
|
1072c8 |
cmd[4] = sizeof(buf);
|
|
|
1072c8 |
|
|
|
1072c8 |
ret = scsi_SG_IO_FROM_DEV(s->conf.blk, cmd, sizeof(cmd),
|
|
|
1072c8 |
- buf, sizeof(buf));
|
|
|
1072c8 |
+ buf, sizeof(buf), s->io_timeout);
|
|
|
1072c8 |
if (ret < 0) {
|
|
|
1072c8 |
return;
|
|
|
1072c8 |
}
|
|
|
1072c8 |
@@ -635,7 +637,7 @@ static int get_stream_blocksize(BlockBackend *blk)
|
|
|
1072c8 |
cmd[0] = MODE_SENSE;
|
|
|
1072c8 |
cmd[4] = sizeof(buf);
|
|
|
1072c8 |
|
|
|
1072c8 |
- ret = scsi_SG_IO_FROM_DEV(blk, cmd, sizeof(cmd), buf, sizeof(buf));
|
|
|
1072c8 |
+ ret = scsi_SG_IO_FROM_DEV(blk, cmd, sizeof(cmd), buf, sizeof(buf), 6);
|
|
|
1072c8 |
if (ret < 0) {
|
|
|
1072c8 |
return -1;
|
|
|
1072c8 |
}
|
|
|
1072c8 |
@@ -725,6 +727,7 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
|
|
|
1072c8 |
|
|
|
1072c8 |
/* Only used by scsi-block, but initialize it nevertheless to be clean. */
|
|
|
1072c8 |
s->default_scsi_version = -1;
|
|
|
1072c8 |
+ s->io_timeout = DEFAULT_IO_TIMEOUT;
|
|
|
1072c8 |
scsi_generic_read_device_inquiry(s);
|
|
|
1072c8 |
}
|
|
|
1072c8 |
|
|
|
1072c8 |
@@ -748,6 +751,8 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
|
|
1072c8 |
static Property scsi_generic_properties[] = {
|
|
|
1072c8 |
DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
|
|
|
1072c8 |
DEFINE_PROP_BOOL("share-rw", SCSIDevice, conf.share_rw, false),
|
|
|
1072c8 |
+ DEFINE_PROP_UINT32("io_timeout", SCSIDevice, io_timeout,
|
|
|
1072c8 |
+ DEFAULT_IO_TIMEOUT),
|
|
|
1072c8 |
DEFINE_PROP_END_OF_LIST(),
|
|
|
1072c8 |
};
|
|
|
1072c8 |
|
|
|
1072c8 |
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
|
|
|
1072c8 |
index 332ef602f4..ae0724a32d 100644
|
|
|
1072c8 |
--- a/include/hw/scsi/scsi.h
|
|
|
1072c8 |
+++ b/include/hw/scsi/scsi.h
|
|
|
1072c8 |
@@ -17,6 +17,7 @@ typedef struct SCSIReqOps SCSIReqOps;
|
|
|
1072c8 |
|
|
|
1072c8 |
#define SCSI_SENSE_BUF_SIZE_OLD 96
|
|
|
1072c8 |
#define SCSI_SENSE_BUF_SIZE 252
|
|
|
1072c8 |
+#define DEFAULT_IO_TIMEOUT 30
|
|
|
1072c8 |
|
|
|
1072c8 |
struct SCSIRequest {
|
|
|
1072c8 |
SCSIBus *bus;
|
|
|
1072c8 |
@@ -88,6 +89,7 @@ struct SCSIDevice
|
|
|
1072c8 |
uint64_t port_wwn;
|
|
|
1072c8 |
int scsi_version;
|
|
|
1072c8 |
int default_scsi_version;
|
|
|
1072c8 |
+ uint32_t io_timeout;
|
|
|
1072c8 |
bool needs_vpd_bl_emulation;
|
|
|
1072c8 |
bool hba_supports_iothread;
|
|
|
1072c8 |
};
|
|
|
1072c8 |
@@ -192,7 +194,7 @@ void scsi_device_unit_attention_reported(SCSIDevice *dev);
|
|
|
1072c8 |
void scsi_generic_read_device_inquiry(SCSIDevice *dev);
|
|
|
1072c8 |
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
|
|
|
1072c8 |
int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
|
|
|
1072c8 |
- uint8_t *buf, uint8_t buf_size);
|
|
|
1072c8 |
+ uint8_t *buf, uint8_t buf_size, uint32_t timeout);
|
|
|
1072c8 |
SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
|
|
|
1072c8 |
|
|
|
1072c8 |
/* scsi-generic.c. */
|
|
|
1072c8 |
--
|
|
|
1072c8 |
2.18.2
|
|
|
1072c8 |
|