In virtscsi_probe(), virtio-scsi enumerates all possible
targets, up to VIRTIO_SCSI_MAX_TARGET, to see which of
them are available. During this scan, the initiator
queues up INQUIRY commands for targets that do not exist.
Provide a "max_target" option for vhost-scsi and virtio-scsi
devices to change the upper limit of scanned targets. Move
away from a static virtio_scsi_scsi_config definition in
favor of a dynamically allocated SCSIBusConfig that is
stored by the VirtIOSCSI device.
Cc: Stefano Garzarella <[email protected]>
Cc: Raphael Norwitz <[email protected]>
Signed-off-by: Karolina Stolarek <[email protected]>
---
hw/scsi/vhost-scsi.c | 2 ++
hw/scsi/vhost-user-scsi.c | 2 ++
hw/scsi/virtio-scsi.c | 37 ++++++++++++++++++++++++---------
include/hw/virtio/virtio-scsi.h | 3 +++
4 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 699863cc10..b2e8240344 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -352,6 +352,8 @@ static const Property vhost_scsi_properties[] = {
128),
DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSICommon, conf.seg_max_adjust,
true),
+ DEFINE_PROP_UINT8("max_target", VirtIOSCSICommon, conf.max_target,
+ VIRTIO_SCSI_MAX_TARGET),
DEFINE_PROP_UINT32("max_sectors", VirtIOSCSICommon, conf.max_sectors,
0xFFFF),
DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSICommon, conf.cmd_per_lun,
128),
diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c
index 3612897d4b..4e59f06ea2 100644
--- a/hw/scsi/vhost-user-scsi.c
+++ b/hw/scsi/vhost-user-scsi.c
@@ -352,6 +352,8 @@ static const Property vhost_user_scsi_properties[] = {
VIRTIO_SCSI_AUTO_NUM_QUEUES),
DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSICommon,
conf.virtqueue_size,
128),
+ DEFINE_PROP_UINT8("max_target", VirtIOSCSICommon, conf.max_target,
+ VIRTIO_SCSI_MAX_TARGET),
DEFINE_PROP_UINT32("max_sectors", VirtIOSCSICommon, conf.max_sectors,
0xFFFF),
DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSICommon, conf.cmd_per_lun,
128),
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index f9e4f6fc02..4de06bad3d 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -975,7 +975,7 @@ static void virtio_scsi_get_config(VirtIODevice *vdev,
virtio_stl_p(vdev, &scsiconf->sense_size, s->sense_size);
virtio_stl_p(vdev, &scsiconf->cdb_size, s->cdb_size);
virtio_stw_p(vdev, &scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
- virtio_stw_p(vdev, &scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
+ virtio_stw_p(vdev, &scsiconf->max_target, s->conf.max_target);
virtio_stl_p(vdev, &scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
}
@@ -1264,13 +1264,6 @@ static void virtio_scsi_drained_end(SCSIBus *bus)
}
}
-static struct SCSIBusConfig virtio_scsi_scsi_config = {
- .tcq = true,
- .max_channel = VIRTIO_SCSI_MAX_CHANNEL,
- .max_target = VIRTIO_SCSI_MAX_TARGET,
- .max_lun = VIRTIO_SCSI_MAX_LUN,
-};
-
static const struct SCSIBusOps virtio_scsi_scsi_ops = {
.complete = virtio_scsi_command_complete,
.fail = virtio_scsi_command_failed,
@@ -1324,6 +1317,23 @@ void virtio_scsi_common_realize(DeviceState *dev,
}
}
+static void virtio_scsi_scsi_config_init(VirtIOSCSI *s)
+{
+ s->bus_config = g_malloc(sizeof(SCSIBusConfig));
+
+ s->bus_config->tcq = true;
+ s->bus_config->max_channel = VIRTIO_SCSI_MAX_CHANNEL;
+ s->bus_config->max_target = s->parent_obj.conf.max_target;
+ s->bus_config->max_lun = VIRTIO_SCSI_MAX_LUN;
+}
+
+static void virtio_scsi_scsi_bus_cleanup(VirtIOSCSI *s)
+{
+ qbus_set_hotplug_handler(BUS(&s->bus), NULL);
+ g_free(s->bus_config);
+ s->bus.config = NULL;
+}
+
static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
@@ -1344,13 +1354,18 @@ static void virtio_scsi_device_realize(DeviceState
*dev, Error **errp)
return;
}
+ virtio_scsi_scsi_config_init(s);
scsi_bus_init_named(&s->bus, sizeof(s->bus), dev,
- &virtio_scsi_scsi_ops, &virtio_scsi_scsi_config,
+ &virtio_scsi_scsi_ops, s->bus_config,
vdev->bus_name);
/* override default SCSI bus hotplug-handler, with virtio-scsi's one */
qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev));
virtio_scsi_dataplane_setup(s, errp);
+
+ if (*errp) {
+ virtio_scsi_scsi_bus_cleanup(s);
+ }
}
void virtio_scsi_common_unrealize(DeviceState *dev)
@@ -1374,7 +1389,7 @@ static void virtio_scsi_device_unrealize(DeviceState *dev)
VirtIOSCSI *s = VIRTIO_SCSI(dev);
virtio_scsi_dataplane_cleanup(s);
- qbus_set_hotplug_handler(BUS(&s->bus), NULL);
+ virtio_scsi_scsi_bus_cleanup(s);
virtio_scsi_common_unrealize(dev);
qemu_mutex_destroy(&s->event_lock);
qemu_mutex_destroy(&s->ctrl_lock);
@@ -1387,6 +1402,8 @@ static const Property virtio_scsi_properties[] = {
parent_obj.conf.virtqueue_size, 256),
DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSI,
parent_obj.conf.seg_max_adjust, true),
+ DEFINE_PROP_UINT8("max_target", VirtIOSCSICommon, conf.max_target,
+ VIRTIO_SCSI_MAX_TARGET),
DEFINE_PROP_UINT32("max_sectors", VirtIOSCSI, parent_obj.conf.max_sectors,
0xFFFF),
DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSI, parent_obj.conf.cmd_per_lun,
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index b6028bb5cd..b4b796fc58 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -54,6 +54,7 @@ struct VirtIOSCSIConf {
uint32_t virtqueue_size;
bool worker_per_virtqueue;
bool seg_max_adjust;
+ uint8_t max_target;
uint32_t max_sectors;
uint32_t cmd_per_lun;
char *vhostfd;
@@ -83,6 +84,8 @@ struct VirtIOSCSI {
VirtIOSCSICommon parent_obj;
SCSIBus bus;
+ SCSIBusConfig *bus_config;
+
int resetting; /* written from main loop thread, read from any thread */
QemuMutex event_lock; /* protects event_vq and events_dropped */