diff mbox series

[v5,3/5] virtio-scsi: default num_queues to -smp N

Message ID 20200706135650.438362-4-stefanha@redhat.com (mailing list archive)
State New, archived
Headers show
Series virtio-pci: enable blk and scsi multi-queue by default | expand

Commit Message

Stefan Hajnoczi July 6, 2020, 1:56 p.m. UTC
Automatically size the number of virtio-scsi-pci, vhost-scsi-pci, and
vhost-user-scsi-pci request virtqueues to match the number of vCPUs.
Other transports continue to default to 1 request virtqueue.

A 1:1 virtqueue:vCPU mapping ensures that completion interrupts are
handled on the same vCPU that submitted the request.  No IPI is
necessary to complete an I/O request and performance is improved.  The
maximum number of MSI-X vectors and virtqueues limit are respected.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 include/hw/virtio/virtio-scsi.h |  2 ++
 hw/core/machine.c               |  3 +++
 hw/scsi/vhost-scsi.c            |  3 ++-
 hw/scsi/vhost-user-scsi.c       |  3 ++-
 hw/scsi/virtio-scsi.c           |  6 +++++-
 hw/virtio/vhost-scsi-pci.c      | 10 +++++++---
 hw/virtio/vhost-user-scsi-pci.c | 10 +++++++---
 hw/virtio/virtio-scsi-pci.c     | 10 +++++++---
 8 files changed, 35 insertions(+), 12 deletions(-)

Comments

Cornelia Huck July 7, 2020, 3:44 p.m. UTC | #1
On Mon,  6 Jul 2020 14:56:48 +0100
Stefan Hajnoczi <stefanha@redhat.com> wrote:

Maybe mention 'pci' in the subject as well?

> Automatically size the number of virtio-scsi-pci, vhost-scsi-pci, and
> vhost-user-scsi-pci request virtqueues to match the number of vCPUs.
> Other transports continue to default to 1 request virtqueue.
> 
> A 1:1 virtqueue:vCPU mapping ensures that completion interrupts are
> handled on the same vCPU that submitted the request.  No IPI is
> necessary to complete an I/O request and performance is improved.  The
> maximum number of MSI-X vectors and virtqueues limit are respected.
> 
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  include/hw/virtio/virtio-scsi.h |  2 ++
>  hw/core/machine.c               |  3 +++
>  hw/scsi/vhost-scsi.c            |  3 ++-
>  hw/scsi/vhost-user-scsi.c       |  3 ++-
>  hw/scsi/virtio-scsi.c           |  6 +++++-
>  hw/virtio/vhost-scsi-pci.c      | 10 +++++++---
>  hw/virtio/vhost-user-scsi-pci.c | 10 +++++++---
>  hw/virtio/virtio-scsi-pci.c     | 10 +++++++---
>  8 files changed, 35 insertions(+), 12 deletions(-)

(...)

> diff --git a/hw/virtio/virtio-scsi-pci.c b/hw/virtio/virtio-scsi-pci.c
> index 3ff9eb7ef6..fa4b3bfb50 100644
> --- a/hw/virtio/virtio-scsi-pci.c
> +++ b/hw/virtio/virtio-scsi-pci.c
> @@ -46,13 +46,17 @@ static void virtio_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
>  {
>      VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev);
>      DeviceState *vdev = DEVICE(&dev->vdev);
> -    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
>      DeviceState *proxy = DEVICE(vpci_dev);
> +    VirtIOSCSIConf *conf = &dev->vdev.parent_obj.conf;
>      char *bus_name;
>  
> +    if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
> +        conf->num_queues =
> +            virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED);
> +    }
> +
>      if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
> -        vpci_dev->nvectors = vs->conf.num_queues +
> -                             VIRTIO_SCSI_VQ_NUM_FIXED + 1;
> +        vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1;
>      }
>  
>      /*

One corner case where the setup may end up being a bit odd is a
situation where nvectors was specified, but num_queues was not, and the
device suddenly ends up with more queues than vectors. But I don't see
a reason why you would want to specify nvectors but not num_queues in a
real word scenario, so I think we can ignore that corner case.

Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Stefan Hajnoczi July 8, 2020, 1:05 p.m. UTC | #2
On Tue, Jul 07, 2020 at 05:44:53PM +0200, Cornelia Huck wrote:
> On Mon,  6 Jul 2020 14:56:48 +0100
> Stefan Hajnoczi <stefanha@redhat.com> wrote:
> 
> Maybe mention 'pci' in the subject as well?

I think this patch does too many things. I'll split up the generic and
PCI parts so that the commit message is more accurate.

> > Automatically size the number of virtio-scsi-pci, vhost-scsi-pci, and
> > vhost-user-scsi-pci request virtqueues to match the number of vCPUs.
> > Other transports continue to default to 1 request virtqueue.
> > 
> > A 1:1 virtqueue:vCPU mapping ensures that completion interrupts are
> > handled on the same vCPU that submitted the request.  No IPI is
> > necessary to complete an I/O request and performance is improved.  The
> > maximum number of MSI-X vectors and virtqueues limit are respected.
> > 
> > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> > ---
> >  include/hw/virtio/virtio-scsi.h |  2 ++
> >  hw/core/machine.c               |  3 +++
> >  hw/scsi/vhost-scsi.c            |  3 ++-
> >  hw/scsi/vhost-user-scsi.c       |  3 ++-
> >  hw/scsi/virtio-scsi.c           |  6 +++++-
> >  hw/virtio/vhost-scsi-pci.c      | 10 +++++++---
> >  hw/virtio/vhost-user-scsi-pci.c | 10 +++++++---
> >  hw/virtio/virtio-scsi-pci.c     | 10 +++++++---
> >  8 files changed, 35 insertions(+), 12 deletions(-)
> 
> (...)
> 
> > diff --git a/hw/virtio/virtio-scsi-pci.c b/hw/virtio/virtio-scsi-pci.c
> > index 3ff9eb7ef6..fa4b3bfb50 100644
> > --- a/hw/virtio/virtio-scsi-pci.c
> > +++ b/hw/virtio/virtio-scsi-pci.c
> > @@ -46,13 +46,17 @@ static void virtio_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
> >  {
> >      VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev);
> >      DeviceState *vdev = DEVICE(&dev->vdev);
> > -    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
> >      DeviceState *proxy = DEVICE(vpci_dev);
> > +    VirtIOSCSIConf *conf = &dev->vdev.parent_obj.conf;
> >      char *bus_name;
> >  
> > +    if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
> > +        conf->num_queues =
> > +            virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED);
> > +    }
> > +
> >      if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
> > -        vpci_dev->nvectors = vs->conf.num_queues +
> > -                             VIRTIO_SCSI_VQ_NUM_FIXED + 1;
> > +        vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1;
> >      }
> >  
> >      /*
> 
> One corner case where the setup may end up being a bit odd is a
> situation where nvectors was specified, but num_queues was not, and the
> device suddenly ends up with more queues than vectors. But I don't see
> a reason why you would want to specify nvectors but not num_queues in a
> real word scenario, so I think we can ignore that corner case.

I agree, I've ignored that case. Other options include printing a
warning or even an error when num_queues disagrees with nvectors.

> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Stefan Hajnoczi July 8, 2020, 1:08 p.m. UTC | #3
On Tue, Jul 07, 2020 at 05:44:53PM +0200, Cornelia Huck wrote:
> On Mon,  6 Jul 2020 14:56:48 +0100
> Stefan Hajnoczi <stefanha@redhat.com> wrote:
> 
> Maybe mention 'pci' in the subject as well?

Actually splitting up the patch is hard due to the nvectors dependency
on num_queues. I will leave it as a single patch and rewrite the commit
message.

Stefan
Cornelia Huck July 8, 2020, 4:50 p.m. UTC | #4
On Wed, 8 Jul 2020 14:05:26 +0100
Stefan Hajnoczi <stefanha@redhat.com> wrote:

> On Tue, Jul 07, 2020 at 05:44:53PM +0200, Cornelia Huck wrote:
> > On Mon,  6 Jul 2020 14:56:48 +0100
> > Stefan Hajnoczi <stefanha@redhat.com> wrote:

> > > diff --git a/hw/virtio/virtio-scsi-pci.c b/hw/virtio/virtio-scsi-pci.c
> > > index 3ff9eb7ef6..fa4b3bfb50 100644
> > > --- a/hw/virtio/virtio-scsi-pci.c
> > > +++ b/hw/virtio/virtio-scsi-pci.c
> > > @@ -46,13 +46,17 @@ static void virtio_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
> > >  {
> > >      VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev);
> > >      DeviceState *vdev = DEVICE(&dev->vdev);
> > > -    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
> > >      DeviceState *proxy = DEVICE(vpci_dev);
> > > +    VirtIOSCSIConf *conf = &dev->vdev.parent_obj.conf;
> > >      char *bus_name;
> > >  
> > > +    if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
> > > +        conf->num_queues =
> > > +            virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED);
> > > +    }
> > > +
> > >      if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
> > > -        vpci_dev->nvectors = vs->conf.num_queues +
> > > -                             VIRTIO_SCSI_VQ_NUM_FIXED + 1;
> > > +        vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1;
> > >      }
> > >  
> > >      /*  
> > 
> > One corner case where the setup may end up being a bit odd is a
> > situation where nvectors was specified, but num_queues was not, and the
> > device suddenly ends up with more queues than vectors. But I don't see
> > a reason why you would want to specify nvectors but not num_queues in a
> > real word scenario, so I think we can ignore that corner case.  
> 
> I agree, I've ignored that case. Other options include printing a
> warning or even an error when num_queues disagrees with nvectors.

I think an error would be too harsh, but a warning sounds useful.
Stefan Hajnoczi July 13, 2020, 10:22 a.m. UTC | #5
On Wed, Jul 08, 2020 at 06:50:12PM +0200, Cornelia Huck wrote:
> On Wed, 8 Jul 2020 14:05:26 +0100
> Stefan Hajnoczi <stefanha@redhat.com> wrote:
> 
> > On Tue, Jul 07, 2020 at 05:44:53PM +0200, Cornelia Huck wrote:
> > > On Mon,  6 Jul 2020 14:56:48 +0100
> > > Stefan Hajnoczi <stefanha@redhat.com> wrote:
> 
> > > > diff --git a/hw/virtio/virtio-scsi-pci.c b/hw/virtio/virtio-scsi-pci.c
> > > > index 3ff9eb7ef6..fa4b3bfb50 100644
> > > > --- a/hw/virtio/virtio-scsi-pci.c
> > > > +++ b/hw/virtio/virtio-scsi-pci.c
> > > > @@ -46,13 +46,17 @@ static void virtio_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
> > > >  {
> > > >      VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev);
> > > >      DeviceState *vdev = DEVICE(&dev->vdev);
> > > > -    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
> > > >      DeviceState *proxy = DEVICE(vpci_dev);
> > > > +    VirtIOSCSIConf *conf = &dev->vdev.parent_obj.conf;
> > > >      char *bus_name;
> > > >  
> > > > +    if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
> > > > +        conf->num_queues =
> > > > +            virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED);
> > > > +    }
> > > > +
> > > >      if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
> > > > -        vpci_dev->nvectors = vs->conf.num_queues +
> > > > -                             VIRTIO_SCSI_VQ_NUM_FIXED + 1;
> > > > +        vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1;
> > > >      }
> > > >  
> > > >      /*  
> > > 
> > > One corner case where the setup may end up being a bit odd is a
> > > situation where nvectors was specified, but num_queues was not, and the
> > > device suddenly ends up with more queues than vectors. But I don't see
> > > a reason why you would want to specify nvectors but not num_queues in a
> > > real word scenario, so I think we can ignore that corner case.  
> > 
> > I agree, I've ignored that case. Other options include printing a
> > warning or even an error when num_queues disagrees with nvectors.
> 
> I think an error would be too harsh, but a warning sounds useful.

I'll send this as a separate patch because at least virtio-serial is
also affected.

Stefan
diff mbox series

Patch

diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 9f293bcb80..c0b8e4dd7e 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -39,6 +39,8 @@ 
 /* Number of virtqueues that are always present */
 #define VIRTIO_SCSI_VQ_NUM_FIXED    2
 
+#define VIRTIO_SCSI_AUTO_NUM_QUEUES UINT32_MAX
+
 typedef struct virtio_scsi_cmd_req VirtIOSCSICmdReq;
 typedef struct virtio_scsi_cmd_resp VirtIOSCSICmdResp;
 typedef struct virtio_scsi_ctrl_tmf_req VirtIOSCSICtrlTMFReq;
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 211b4e077a..3df534405b 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -29,7 +29,10 @@ 
 #include "migration/vmstate.h"
 
 GlobalProperty hw_compat_5_0[] = {
+    { "vhost-scsi", "num_queues", "1"},
+    { "vhost-user-scsi", "num_queues", "1"},
     { "virtio-balloon-device", "page-poison", "false" },
+    { "virtio-scsi-device", "num_queues", "1"},
     { "vmport", "x-read-set-eax", "off" },
     { "vmport", "x-signal-unsupported-cmd", "off" },
     { "vmport", "x-report-vmx-type", "off" },
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index c1b012aea4..5e3bc319ab 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -272,7 +272,8 @@  static Property vhost_scsi_properties[] = {
     DEFINE_PROP_STRING("vhostfd", VirtIOSCSICommon, conf.vhostfd),
     DEFINE_PROP_STRING("wwpn", VirtIOSCSICommon, conf.wwpn),
     DEFINE_PROP_UINT32("boot_tpgt", VirtIOSCSICommon, conf.boot_tpgt, 0),
-    DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues, 1),
+    DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues,
+                       VIRTIO_SCSI_AUTO_NUM_QUEUES),
     DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSICommon, conf.virtqueue_size,
                        128),
     DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSICommon, conf.seg_max_adjust,
diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c
index a8b821466f..7c0631656c 100644
--- a/hw/scsi/vhost-user-scsi.c
+++ b/hw/scsi/vhost-user-scsi.c
@@ -162,7 +162,8 @@  static void vhost_user_scsi_unrealize(DeviceState *dev)
 static Property vhost_user_scsi_properties[] = {
     DEFINE_PROP_CHR("chardev", VirtIOSCSICommon, conf.chardev),
     DEFINE_PROP_UINT32("boot_tpgt", VirtIOSCSICommon, conf.boot_tpgt, 0),
-    DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues, 1),
+    DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues,
+                       VIRTIO_SCSI_AUTO_NUM_QUEUES),
     DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSICommon, conf.virtqueue_size,
                        128),
     DEFINE_PROP_UINT32("max_sectors", VirtIOSCSICommon, conf.max_sectors,
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index eecdd05af5..3a71ea7097 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -891,6 +891,9 @@  void virtio_scsi_common_realize(DeviceState *dev,
     virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI,
                 sizeof(VirtIOSCSIConfig));
 
+    if (s->conf.num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
+        s->conf.num_queues = 1;
+    }
     if (s->conf.num_queues == 0 ||
             s->conf.num_queues > VIRTIO_QUEUE_MAX - VIRTIO_SCSI_VQ_NUM_FIXED) {
         error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
@@ -964,7 +967,8 @@  static void virtio_scsi_device_unrealize(DeviceState *dev)
 }
 
 static Property virtio_scsi_properties[] = {
-    DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues, 1),
+    DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues,
+                       VIRTIO_SCSI_AUTO_NUM_QUEUES),
     DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSI,
                                          parent_obj.conf.virtqueue_size, 256),
     DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSI,
diff --git a/hw/virtio/vhost-scsi-pci.c b/hw/virtio/vhost-scsi-pci.c
index 06e814d30e..a6bb0dc60d 100644
--- a/hw/virtio/vhost-scsi-pci.c
+++ b/hw/virtio/vhost-scsi-pci.c
@@ -47,11 +47,15 @@  static void vhost_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
 {
     VHostSCSIPCI *dev = VHOST_SCSI_PCI(vpci_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
-    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
+    VirtIOSCSIConf *conf = &dev->vdev.parent_obj.parent_obj.conf;
+
+    if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
+        conf->num_queues =
+            virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED);
+    }
 
     if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
-        vpci_dev->nvectors = vs->conf.num_queues +
-                             VIRTIO_SCSI_VQ_NUM_FIXED + 1;
+        vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1;
     }
 
     qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
diff --git a/hw/virtio/vhost-user-scsi-pci.c b/hw/virtio/vhost-user-scsi-pci.c
index ab6dfb71a9..25e97ca54e 100644
--- a/hw/virtio/vhost-user-scsi-pci.c
+++ b/hw/virtio/vhost-user-scsi-pci.c
@@ -53,11 +53,15 @@  static void vhost_user_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
 {
     VHostUserSCSIPCI *dev = VHOST_USER_SCSI_PCI(vpci_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
-    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
+    VirtIOSCSIConf *conf = &dev->vdev.parent_obj.parent_obj.conf;
+
+    if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
+        conf->num_queues =
+            virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED);
+    }
 
     if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
-        vpci_dev->nvectors = vs->conf.num_queues +
-                             VIRTIO_SCSI_VQ_NUM_FIXED + 1;
+        vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1;
     }
 
     qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
diff --git a/hw/virtio/virtio-scsi-pci.c b/hw/virtio/virtio-scsi-pci.c
index 3ff9eb7ef6..fa4b3bfb50 100644
--- a/hw/virtio/virtio-scsi-pci.c
+++ b/hw/virtio/virtio-scsi-pci.c
@@ -46,13 +46,17 @@  static void virtio_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
 {
     VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
-    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
     DeviceState *proxy = DEVICE(vpci_dev);
+    VirtIOSCSIConf *conf = &dev->vdev.parent_obj.conf;
     char *bus_name;
 
+    if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
+        conf->num_queues =
+            virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED);
+    }
+
     if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
-        vpci_dev->nvectors = vs->conf.num_queues +
-                             VIRTIO_SCSI_VQ_NUM_FIXED + 1;
+        vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1;
     }
 
     /*