* [PATCH 0/2] virtio-scsi: Flexible max_target and max_lun params
@ 2025-11-25 11:01 Karolina Stolarek
2025-11-25 11:01 ` [PATCH 1/2] virtio-scsi: Make max_target value configurable Karolina Stolarek
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Karolina Stolarek @ 2025-11-25 11:01 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S . Tsirkin, Stefano Garzarella, Paolo Bonzini, Fam Zheng,
Mike Christie
Currently, the maximum number of targets is set and dictated
by virtio-scsi. On probe, the driver walks through all possible
targets to discover which of them are available. In the process,
it sends INQUIRY commands to request device information, also
querying devices that don't exist. This can be observed in
a guest with a single scsi-hd device and verbose SCSI logging
enabled:
scsi 0:0:0:0: scsi scan: REPORT LUN scan
scsi 0:0:0:0: scsi scan: device exists on 0:0:0:0
scsi 0:0:1:0: scsi scan: INQUIRY pass 1 length 36
scsi 0:0:1:0: scsi scan: INQUIRY failed with code 0x40000
(...)
scsi 0:0:255:0: scsi scan: INQUIRY pass 1 length 36
scsi 0:0:255:0: scsi scan: INQUIRY failed with code 0x40000
In the vhost-scsi backend, without the kernel patch [1], the issue
is far more noticeable. Each command queued up for a non-existing
target triggers vq_error(), registered by
vhost_virtqueue_error_notifier(), resulting in a flood of
"vhost vring error in virtqueue X" messages when booting up a VM.
Even with the [1] patch in place, we are still sending commands
to phantom targets with no way of limiting the scan. The first
patch in the series addresses this issue by introducing "max_target"
property for virtio-scsi and vhost-scsi devices. A user gets
an option to specify how many targets are used by the guest,
and to stop scanning before hitting VIRTIO_SCSI_MAX_TARGET.
A similar issue can be seen with Logical Units in the existing
devices. By default, the SCSI Host Adapter instance expects
8 LUNs, and some drivers assume this to be the actual number
of exposed LUNs. This results in executing SCSI commands that
refer to non-existing Logical Units. This can be easily observed
when using vhost-scsi backend, as such messages appear in
the host's dmesg when booting up a guest:
TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000001 from
naa.5001405277e02c68
TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000002 from
naa.5001405277e02c68
TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000003 from
naa.5001405277e02c68
TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000004 from
naa.5001405277e02c68
TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000005 from
naa.5001405277e02c68
TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000006 from
naa.5001405277e02c68
TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000007 from
naa.5001405277e02c68
The second patch provides a way to say how many LUNs are actually
there by setting "max_lun" property in virtio-scsi and vhost-scsi
devices. If neither property is defined, max_target and max_lun are
set to the default values, making these definitions optional.
----------------------------
[1] -
https://lore.kernel.org/virtualization/20250607171815.111030-1-michael.christie@oracle.com/T/#u
Karolina Stolarek (2):
virtio-scsi: Make max_target value configurable
virtio-scsi: Make max_lun value configurable
hw/scsi/vhost-scsi.c | 4 +++
hw/scsi/virtio-scsi.c | 46 +++++++++++++++++++--------------
include/hw/virtio/virtio-scsi.h | 2 ++
3 files changed, 33 insertions(+), 19 deletions(-)
--
2.47.1
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 1/2] virtio-scsi: Make max_target value configurable 2025-11-25 11:01 [PATCH 0/2] virtio-scsi: Flexible max_target and max_lun params Karolina Stolarek @ 2025-11-25 11:01 ` Karolina Stolarek 2025-12-08 13:54 ` Alex Bennée 2025-11-25 11:01 ` [PATCH 2/2] virtio-scsi: Make max_lun " Karolina Stolarek 2025-12-08 12:18 ` [PATCH 0/2] virtio-scsi: Flexible max_target and max_lun params Karolina Stolarek 2 siblings, 1 reply; 6+ messages in thread From: Karolina Stolarek @ 2025-11-25 11:01 UTC (permalink / raw) To: qemu-devel Cc: Michael S . Tsirkin, Stefano Garzarella, Paolo Bonzini, Fam Zheng, Mike Christie In virtiscsi_probe(), virtio-scsi enumerates all possible targets, up to VIRTIO_SCSI_MAX_TARGET, to see which of them are available. This means that during that scan, the initiator queues up INQUIRY commands to the targets that do not exist. Such inquires fail, returning a BAD_TARGET response. Currently, there is no way to limit the number of possible targets or to finish the scan earlier. Add "max_target" option for virtio-scsi and vhost-scsi devices to provide a hint on the number of targets available for scanning. Signed-off-by: Karolina Stolarek <karolina.stolarek@oracle.com> --- hw/scsi/vhost-scsi.c | 2 ++ hw/scsi/virtio-scsi.c | 42 +++++++++++++++++++-------------- include/hw/virtio/virtio-scsi.h | 1 + 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index cdf405b0f8..1a4860a72f 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -353,6 +353,8 @@ static const Property vhost_scsi_properties[] = { 128), DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSICommon, conf.seg_max_adjust, true), + DEFINE_PROP_UINT16("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 93e87c459c..091f68090e 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -971,7 +971,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); } @@ -1260,23 +1260,26 @@ static void virtio_scsi_drained_end(SCSIBus *bus) } } -static struct SCSIBusInfo virtio_scsi_scsi_info = { - .tcq = true, - .max_channel = VIRTIO_SCSI_MAX_CHANNEL, - .max_target = VIRTIO_SCSI_MAX_TARGET, - .max_lun = VIRTIO_SCSI_MAX_LUN, - - .complete = virtio_scsi_command_complete, - .fail = virtio_scsi_command_failed, - .cancel = virtio_scsi_request_cancelled, - .change = virtio_scsi_change, - .parse_cdb = virtio_scsi_parse_cdb, - .get_sg_list = virtio_scsi_get_sg_list, - .save_request = virtio_scsi_save_request, - .load_request = virtio_scsi_load_request, - .drained_begin = virtio_scsi_drained_begin, - .drained_end = virtio_scsi_drained_end, -}; +static struct SCSIBusInfo virtio_scsi_scsi_info; + +static void virtio_scsi_init_scsi_info(struct VirtIOSCSIConf *conf) +{ + virtio_scsi_scsi_info.tcq = true; + virtio_scsi_scsi_info.max_channel = VIRTIO_SCSI_MAX_CHANNEL; + virtio_scsi_scsi_info.max_lun = VIRTIO_SCSI_MAX_LUN; + virtio_scsi_scsi_info.max_target = conf->max_target; + + virtio_scsi_scsi_info.complete = virtio_scsi_command_complete; + virtio_scsi_scsi_info.fail = virtio_scsi_command_failed; + virtio_scsi_scsi_info.cancel = virtio_scsi_request_cancelled; + virtio_scsi_scsi_info.change = virtio_scsi_change; + virtio_scsi_scsi_info.parse_cdb = virtio_scsi_parse_cdb; + virtio_scsi_scsi_info.get_sg_list = virtio_scsi_get_sg_list; + virtio_scsi_scsi_info.save_request = virtio_scsi_save_request; + virtio_scsi_scsi_info.load_request = virtio_scsi_load_request; + virtio_scsi_scsi_info.drained_begin = virtio_scsi_drained_begin; + virtio_scsi_scsi_info.drained_end = virtio_scsi_drained_end; +} void virtio_scsi_common_realize(DeviceState *dev, VirtIOHandleOutput ctrl, @@ -1289,6 +1292,7 @@ void virtio_scsi_common_realize(DeviceState *dev, int i; virtio_init(vdev, VIRTIO_ID_SCSI, sizeof(VirtIOSCSIConfig)); + virtio_scsi_init_scsi_info(&s->conf); if (s->conf.num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) { s->conf.num_queues = 1; @@ -1379,6 +1383,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_UINT16("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..3998b241f6 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; + uint16_t max_target; uint32_t max_sectors; uint32_t cmd_per_lun; char *vhostfd; -- 2.47.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] virtio-scsi: Make max_target value configurable 2025-11-25 11:01 ` [PATCH 1/2] virtio-scsi: Make max_target value configurable Karolina Stolarek @ 2025-12-08 13:54 ` Alex Bennée 2025-12-10 16:55 ` Karolina Stolarek 0 siblings, 1 reply; 6+ messages in thread From: Alex Bennée @ 2025-12-08 13:54 UTC (permalink / raw) To: Karolina Stolarek Cc: qemu-devel, Michael S . Tsirkin, Stefano Garzarella, Paolo Bonzini, Fam Zheng, Mike Christie Karolina Stolarek <karolina.stolarek@oracle.com> writes: > In virtiscsi_probe(), virtio-scsi enumerates all possible > targets, up to VIRTIO_SCSI_MAX_TARGET, to see which of them > are available. This means that during that scan, the initiator > queues up INQUIRY commands to the targets that do not exist. > Such inquires fail, returning a BAD_TARGET response. > > Currently, there is no way to limit the number of possible > targets or to finish the scan earlier. Add "max_target" > option for virtio-scsi and vhost-scsi devices to provide > a hint on the number of targets available for scanning. > > Signed-off-by: Karolina Stolarek <karolina.stolarek@oracle.com> > --- > hw/scsi/vhost-scsi.c | 2 ++ > hw/scsi/virtio-scsi.c | 42 +++++++++++++++++++-------------- > include/hw/virtio/virtio-scsi.h | 1 + > 3 files changed, 27 insertions(+), 18 deletions(-) > > diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c > index cdf405b0f8..1a4860a72f 100644 > --- a/hw/scsi/vhost-scsi.c > +++ b/hw/scsi/vhost-scsi.c > @@ -353,6 +353,8 @@ static const Property vhost_scsi_properties[] = { > 128), > DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSICommon, conf.seg_max_adjust, > true), > + DEFINE_PROP_UINT16("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 93e87c459c..091f68090e 100644 > --- a/hw/scsi/virtio-scsi.c > +++ b/hw/scsi/virtio-scsi.c > @@ -971,7 +971,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); > } > > @@ -1260,23 +1260,26 @@ static void virtio_scsi_drained_end(SCSIBus *bus) > } > } > > -static struct SCSIBusInfo virtio_scsi_scsi_info = { > - .tcq = true, > - .max_channel = VIRTIO_SCSI_MAX_CHANNEL, > - .max_target = VIRTIO_SCSI_MAX_TARGET, > - .max_lun = VIRTIO_SCSI_MAX_LUN, See bellow. > - > - .complete = virtio_scsi_command_complete, > - .fail = virtio_scsi_command_failed, > - .cancel = virtio_scsi_request_cancelled, > - .change = virtio_scsi_change, > - .parse_cdb = virtio_scsi_parse_cdb, > - .get_sg_list = virtio_scsi_get_sg_list, > - .save_request = virtio_scsi_save_request, > - .load_request = virtio_scsi_load_request, > - .drained_begin = virtio_scsi_drained_begin, > - .drained_end = virtio_scsi_drained_end, > -}; > +static struct SCSIBusInfo virtio_scsi_scsi_info; > + We can't have a static structure here otherwise all the VirtIO scsi devices will share the same configuration. > +static void virtio_scsi_init_scsi_info(struct VirtIOSCSIConf *conf) > +{ > + virtio_scsi_scsi_info.tcq = true; > + virtio_scsi_scsi_info.max_channel = VIRTIO_SCSI_MAX_CHANNEL; > + virtio_scsi_scsi_info.max_lun = VIRTIO_SCSI_MAX_LUN; > + virtio_scsi_scsi_info.max_target = conf->max_target; I think we need to allocate a dynamic configuration block for this stuff. Although given we have ops and config mixed in this structure I suspect the cleaner option is to re-factor SCSIBusInfo into SCSIBusConfig and SCSIBusOps so you can keep the static around. But this would touch quite a bit of code. > + > + virtio_scsi_scsi_info.complete = virtio_scsi_command_complete; > + virtio_scsi_scsi_info.fail = virtio_scsi_command_failed; > + virtio_scsi_scsi_info.cancel = virtio_scsi_request_cancelled; > + virtio_scsi_scsi_info.change = virtio_scsi_change; > + virtio_scsi_scsi_info.parse_cdb = virtio_scsi_parse_cdb; > + virtio_scsi_scsi_info.get_sg_list = virtio_scsi_get_sg_list; > + virtio_scsi_scsi_info.save_request = virtio_scsi_save_request; > + virtio_scsi_scsi_info.load_request = virtio_scsi_load_request; > + virtio_scsi_scsi_info.drained_begin = virtio_scsi_drained_begin; > + virtio_scsi_scsi_info.drained_end = virtio_scsi_drained_end; > +} > > void virtio_scsi_common_realize(DeviceState *dev, > VirtIOHandleOutput ctrl, > @@ -1289,6 +1292,7 @@ void virtio_scsi_common_realize(DeviceState *dev, > int i; > > virtio_init(vdev, VIRTIO_ID_SCSI, sizeof(VirtIOSCSIConfig)); > + virtio_scsi_init_scsi_info(&s->conf); > > if (s->conf.num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) { > s->conf.num_queues = 1; > @@ -1379,6 +1383,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_UINT16("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..3998b241f6 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; > + uint16_t max_target; > uint32_t max_sectors; > uint32_t cmd_per_lun; > char *vhostfd; -- Alex Bennée Virtualisation Tech Lead @ Linaro ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] virtio-scsi: Make max_target value configurable 2025-12-08 13:54 ` Alex Bennée @ 2025-12-10 16:55 ` Karolina Stolarek 0 siblings, 0 replies; 6+ messages in thread From: Karolina Stolarek @ 2025-12-10 16:55 UTC (permalink / raw) To: Alex Bennée Cc: qemu-devel, Michael S . Tsirkin, Stefano Garzarella, Paolo Bonzini, Fam Zheng, Mike Christie On 08/12/2025 14:54, Alex Bennée wrote: > Karolina Stolarek <karolina.stolarek@oracle.com> writes: > >> -static struct SCSIBusInfo virtio_scsi_scsi_info = { >> - .tcq = true, >> - .max_channel = VIRTIO_SCSI_MAX_CHANNEL, >> - .max_target = VIRTIO_SCSI_MAX_TARGET, >> - .max_lun = VIRTIO_SCSI_MAX_LUN, > > See bellow. > >> - >> - .complete = virtio_scsi_command_complete, >> - .fail = virtio_scsi_command_failed, >> - .cancel = virtio_scsi_request_cancelled, >> - .change = virtio_scsi_change, >> - .parse_cdb = virtio_scsi_parse_cdb, >> - .get_sg_list = virtio_scsi_get_sg_list, >> - .save_request = virtio_scsi_save_request, >> - .load_request = virtio_scsi_load_request, >> - .drained_begin = virtio_scsi_drained_begin, >> - .drained_end = virtio_scsi_drained_end, >> -}; >> +static struct SCSIBusInfo virtio_scsi_scsi_info; >> + > > We can't have a static structure here otherwise all the VirtIO scsi > devices will share the same configuration. Ah, that is true, it escaped me. > >> +static void virtio_scsi_init_scsi_info(struct VirtIOSCSIConf *conf) >> +{ >> + virtio_scsi_scsi_info.tcq = true; >> + virtio_scsi_scsi_info.max_channel = VIRTIO_SCSI_MAX_CHANNEL; >> + virtio_scsi_scsi_info.max_lun = VIRTIO_SCSI_MAX_LUN; >> + virtio_scsi_scsi_info.max_target = conf->max_target; > > I think we need to allocate a dynamic configuration block for this > stuff. Although given we have ops and config mixed in this structure I > suspect the cleaner option is to re-factor SCSIBusInfo into > SCSIBusConfig and SCSIBusOps so you can keep the static around. But this > would touch quite a bit of code. I understand, that sounds like a better solution. It might take some time to finalize this, but I'd like to try it for v2. Many thanks for your review, really appreciate it. All the best, Karolina > >> + >> + virtio_scsi_scsi_info.complete = virtio_scsi_command_complete; >> + virtio_scsi_scsi_info.fail = virtio_scsi_command_failed; >> + virtio_scsi_scsi_info.cancel = virtio_scsi_request_cancelled; >> + virtio_scsi_scsi_info.change = virtio_scsi_change; >> + virtio_scsi_scsi_info.parse_cdb = virtio_scsi_parse_cdb; >> + virtio_scsi_scsi_info.get_sg_list = virtio_scsi_get_sg_list; >> + virtio_scsi_scsi_info.save_request = virtio_scsi_save_request; >> + virtio_scsi_scsi_info.load_request = virtio_scsi_load_request; >> + virtio_scsi_scsi_info.drained_begin = virtio_scsi_drained_begin; >> + virtio_scsi_scsi_info.drained_end = virtio_scsi_drained_end; >> +} >> >> void virtio_scsi_common_realize(DeviceState *dev, >> VirtIOHandleOutput ctrl, >> @@ -1289,6 +1292,7 @@ void virtio_scsi_common_realize(DeviceState *dev, >> int i; >> >> virtio_init(vdev, VIRTIO_ID_SCSI, sizeof(VirtIOSCSIConfig)); >> + virtio_scsi_init_scsi_info(&s->conf); >> >> if (s->conf.num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) { >> s->conf.num_queues = 1; >> @@ -1379,6 +1383,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_UINT16("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..3998b241f6 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; >> + uint16_t max_target; >> uint32_t max_sectors; >> uint32_t cmd_per_lun; >> char *vhostfd; > ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] virtio-scsi: Make max_lun value configurable 2025-11-25 11:01 [PATCH 0/2] virtio-scsi: Flexible max_target and max_lun params Karolina Stolarek 2025-11-25 11:01 ` [PATCH 1/2] virtio-scsi: Make max_target value configurable Karolina Stolarek @ 2025-11-25 11:01 ` Karolina Stolarek 2025-12-08 12:18 ` [PATCH 0/2] virtio-scsi: Flexible max_target and max_lun params Karolina Stolarek 2 siblings, 0 replies; 6+ messages in thread From: Karolina Stolarek @ 2025-11-25 11:01 UTC (permalink / raw) To: qemu-devel Cc: Michael S . Tsirkin, Stefano Garzarella, Paolo Bonzini, Fam Zheng, Mike Christie By default, the host adapter instance expects the maximum of 8 LUNs. The virtio-scsi driver doesn't override this value, as it queries for the actual number of the Logical Units during virtscsi_probe(). Still, some drivers do not perform such scan and assume the virtio_scsi_scsi_info.max_lun value to be definite and correct, which might not be true. This can result in the driver queuing up SCSI commands referring to LUNs that do not exist. Add "max_lun" option to virtio-scsi and vhost-scsi devices to specify the maximum number of LUNs to prevent sending commands to Logical Units that do not exist. Signed-off-by: Karolina Stolarek <karolina.stolarek@oracle.com> --- hw/scsi/vhost-scsi.c | 2 ++ hw/scsi/virtio-scsi.c | 6 ++++-- include/hw/virtio/virtio-scsi.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index 1a4860a72f..6883629170 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -355,6 +355,8 @@ static const Property vhost_scsi_properties[] = { true), DEFINE_PROP_UINT16("max_target", VirtIOSCSICommon, conf.max_target, VIRTIO_SCSI_MAX_TARGET), + DEFINE_PROP_UINT32("max_lun", VirtIOSCSICommon, conf.max_lun, + VIRTIO_SCSI_MAX_LUN), 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 091f68090e..9e7eebd835 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -972,7 +972,7 @@ static void virtio_scsi_get_config(VirtIODevice *vdev, 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, s->conf.max_target); - virtio_stl_p(vdev, &scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN); + virtio_stl_p(vdev, &scsiconf->max_lun, s->conf.max_lun); } static void virtio_scsi_set_config(VirtIODevice *vdev, @@ -1266,7 +1266,7 @@ static void virtio_scsi_init_scsi_info(struct VirtIOSCSIConf *conf) { virtio_scsi_scsi_info.tcq = true; virtio_scsi_scsi_info.max_channel = VIRTIO_SCSI_MAX_CHANNEL; - virtio_scsi_scsi_info.max_lun = VIRTIO_SCSI_MAX_LUN; + virtio_scsi_scsi_info.max_lun = conf->max_lun; virtio_scsi_scsi_info.max_target = conf->max_target; virtio_scsi_scsi_info.complete = virtio_scsi_command_complete; @@ -1385,6 +1385,8 @@ static const Property virtio_scsi_properties[] = { parent_obj.conf.seg_max_adjust, true), DEFINE_PROP_UINT16("max_target", VirtIOSCSICommon, conf.max_target, VIRTIO_SCSI_MAX_TARGET), + DEFINE_PROP_UINT32("max_lun", VirtIOSCSICommon, conf.max_lun, + VIRTIO_SCSI_MAX_LUN), 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 3998b241f6..61fe5cae34 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -55,6 +55,7 @@ struct VirtIOSCSIConf { bool worker_per_virtqueue; bool seg_max_adjust; uint16_t max_target; + uint32_t max_lun; uint32_t max_sectors; uint32_t cmd_per_lun; char *vhostfd; -- 2.47.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] virtio-scsi: Flexible max_target and max_lun params 2025-11-25 11:01 [PATCH 0/2] virtio-scsi: Flexible max_target and max_lun params Karolina Stolarek 2025-11-25 11:01 ` [PATCH 1/2] virtio-scsi: Make max_target value configurable Karolina Stolarek 2025-11-25 11:01 ` [PATCH 2/2] virtio-scsi: Make max_lun " Karolina Stolarek @ 2025-12-08 12:18 ` Karolina Stolarek 2 siblings, 0 replies; 6+ messages in thread From: Karolina Stolarek @ 2025-12-08 12:18 UTC (permalink / raw) To: qemu-devel Cc: Michael S . Tsirkin, Stefano Garzarella, Paolo Bonzini, Fam Zheng, Mike Christie Hi, On 25/11/2025 12:01, Karolina Stolarek wrote: > Currently, the maximum number of targets is set and dictated > by virtio-scsi. On probe, the driver walks through all possible > targets to discover which of them are available. In the process, > it sends INQUIRY commands to request device information, also > querying devices that don't exist. This can be observed in > a guest with a single scsi-hd device and verbose SCSI logging > enabled: A gentle ping on this one. All the best, Karolina > > scsi 0:0:0:0: scsi scan: REPORT LUN scan > scsi 0:0:0:0: scsi scan: device exists on 0:0:0:0 > scsi 0:0:1:0: scsi scan: INQUIRY pass 1 length 36 > scsi 0:0:1:0: scsi scan: INQUIRY failed with code 0x40000 > (...) > scsi 0:0:255:0: scsi scan: INQUIRY pass 1 length 36 > scsi 0:0:255:0: scsi scan: INQUIRY failed with code 0x40000 > > In the vhost-scsi backend, without the kernel patch [1], the issue > is far more noticeable. Each command queued up for a non-existing > target triggers vq_error(), registered by > vhost_virtqueue_error_notifier(), resulting in a flood of > "vhost vring error in virtqueue X" messages when booting up a VM. > Even with the [1] patch in place, we are still sending commands > to phantom targets with no way of limiting the scan. The first > patch in the series addresses this issue by introducing "max_target" > property for virtio-scsi and vhost-scsi devices. A user gets > an option to specify how many targets are used by the guest, > and to stop scanning before hitting VIRTIO_SCSI_MAX_TARGET. > > A similar issue can be seen with Logical Units in the existing > devices. By default, the SCSI Host Adapter instance expects > 8 LUNs, and some drivers assume this to be the actual number > of exposed LUNs. This results in executing SCSI commands that > refer to non-existing Logical Units. This can be easily observed > when using vhost-scsi backend, as such messages appear in > the host's dmesg when booting up a guest: > > TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000001 from > naa.5001405277e02c68 > TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000002 from > naa.5001405277e02c68 > TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000003 from > naa.5001405277e02c68 > TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000004 from > naa.5001405277e02c68 > TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000005 from > naa.5001405277e02c68 > TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000006 from > naa.5001405277e02c68 > TARGET_CORE[vhost]: Detected NON_EXISTENT_LUN Access for 0x00000007 from > naa.5001405277e02c68 > > The second patch provides a way to say how many LUNs are actually > there by setting "max_lun" property in virtio-scsi and vhost-scsi > devices. If neither property is defined, max_target and max_lun are > set to the default values, making these definitions optional. > > ---------------------------- > [1] - > https://lore.kernel.org/virtualization/20250607171815.111030-1-michael.christie@oracle.com/T/#u > > Karolina Stolarek (2): > virtio-scsi: Make max_target value configurable > virtio-scsi: Make max_lun value configurable > > hw/scsi/vhost-scsi.c | 4 +++ > hw/scsi/virtio-scsi.c | 46 +++++++++++++++++++-------------- > include/hw/virtio/virtio-scsi.h | 2 ++ > 3 files changed, 33 insertions(+), 19 deletions(-) > ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-12-10 16:56 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-11-25 11:01 [PATCH 0/2] virtio-scsi: Flexible max_target and max_lun params Karolina Stolarek 2025-11-25 11:01 ` [PATCH 1/2] virtio-scsi: Make max_target value configurable Karolina Stolarek 2025-12-08 13:54 ` Alex Bennée 2025-12-10 16:55 ` Karolina Stolarek 2025-11-25 11:01 ` [PATCH 2/2] virtio-scsi: Make max_lun " Karolina Stolarek 2025-12-08 12:18 ` [PATCH 0/2] virtio-scsi: Flexible max_target and max_lun params Karolina Stolarek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).