From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51305) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b7Zzd-0000zN-KY for qemu-devel@nongnu.org; Mon, 30 May 2016 23:06:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b7Zyk-0007LY-V7 for qemu-devel@nongnu.org; Mon, 30 May 2016 23:05:21 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41185) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b7Zyk-0007Kx-LZ for qemu-devel@nongnu.org; Mon, 30 May 2016 23:04:26 -0400 References: <1460004984-3784-1-git-send-email-jasowang@redhat.com> <20160530210308-mutt-send-email-mst@redhat.com> From: Jason Wang Message-ID: <574CFF32.2090005@redhat.com> Date: Tue, 31 May 2016 11:04:18 +0800 MIME-Version: 1.0 In-Reply-To: <20160530210308-mutt-send-email-mst@redhat.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH V3] tap: vhost busy polling support List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "Michael S. Tsirkin" Cc: qemu-devel@nongnu.org, eblake@redhat.com, gkurz@linux.vnet.ibm.com, famz@redhat.com On 2016=E5=B9=B405=E6=9C=8831=E6=97=A5 02:07, Michael S. Tsirkin wrote: > On Thu, Apr 07, 2016 at 12:56:24PM +0800, Jason Wang wrote: >> This patch add the capability of basic vhost net busy polling which is >> supported by recent kernel. User could configure the maximum number of >> us that could be spent on busy polling through a new property of tap >> "vhost-poll-us". > I applied this but now I had a thought - should we generalize this to > "poll-us"? Down the road tun could support busy olling just like > sockets do. Looks two different things. Socket busy polling depends on the value set=20 by sysctl or SO_BUSY_POLL, which should be transparent to qemu. >> Signed-off-by: Jason Wang >> --- >> hw/net/vhost_net.c | 2 +- >> hw/scsi/vhost-scsi.c | 2 +- >> hw/virtio/vhost-backend.c | 8 ++++++++ >> hw/virtio/vhost.c | 40 +++++++++++++++++++++++++++++= +++++++++- >> include/hw/virtio/vhost-backend.h | 3 +++ >> include/hw/virtio/vhost.h | 3 ++- >> include/net/vhost_net.h | 1 + >> net/tap.c | 10 ++++++++-- >> net/vhost-user.c | 1 + >> qapi-schema.json | 6 +++++- >> qemu-options.hx | 3 +++ >> 11 files changed, 72 insertions(+), 7 deletions(-) >> >> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c >> index 6e1032f..1840c73 100644 >> --- a/hw/net/vhost_net.c >> +++ b/hw/net/vhost_net.c >> @@ -166,7 +166,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *= options) >> } >> =20 >> r =3D vhost_dev_init(&net->dev, options->opaque, >> - options->backend_type); >> + options->backend_type, options->busyloop_timeo= ut); >> if (r < 0) { >> goto fail; >> } >> diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c >> index 9261d51..2a00f2f 100644 >> --- a/hw/scsi/vhost-scsi.c >> +++ b/hw/scsi/vhost-scsi.c >> @@ -248,7 +248,7 @@ static void vhost_scsi_realize(DeviceState *dev, E= rror **errp) >> s->dev.backend_features =3D 0; >> =20 >> ret =3D vhost_dev_init(&s->dev, (void *)(uintptr_t)vhostfd, >> - VHOST_BACKEND_TYPE_KERNEL); >> + VHOST_BACKEND_TYPE_KERNEL, 0); >> if (ret < 0) { >> error_setg(errp, "vhost-scsi: vhost initialization failed: %= s", >> strerror(-ret)); >> diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c >> index b358902..d62372e 100644 >> --- a/hw/virtio/vhost-backend.c >> +++ b/hw/virtio/vhost-backend.c >> @@ -138,6 +138,12 @@ static int vhost_kernel_set_vring_call(struct vho= st_dev *dev, >> return vhost_kernel_call(dev, VHOST_SET_VRING_CALL, file); >> } >> =20 >> +static int vhost_kernel_set_vring_busyloop_timeout(struct vhost_dev *= dev, >> + struct vhost_vring= _state *s) >> +{ >> + return vhost_kernel_call(dev, VHOST_SET_VRING_BUSYLOOP_TIMEOUT, s= ); >> +} >> + >> static int vhost_kernel_set_features(struct vhost_dev *dev, >> uint64_t features) >> { >> @@ -185,6 +191,8 @@ static const VhostOps kernel_ops =3D { >> .vhost_get_vring_base =3D vhost_kernel_get_vring_base, >> .vhost_set_vring_kick =3D vhost_kernel_set_vring_kick, >> .vhost_set_vring_call =3D vhost_kernel_set_vring_call, >> + .vhost_set_vring_busyloop_timeout =3D >> + vhost_kernel_set_vring_busyloop_timeo= ut, >> .vhost_set_features =3D vhost_kernel_set_features, >> .vhost_get_features =3D vhost_kernel_get_features, >> .vhost_set_owner =3D vhost_kernel_set_owner, >> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c >> index 4400718..ebf8b08 100644 >> --- a/hw/virtio/vhost.c >> +++ b/hw/virtio/vhost.c >> @@ -964,6 +964,28 @@ static void vhost_eventfd_del(MemoryListener *lis= tener, >> { >> } >> =20 >> +static int vhost_virtqueue_set_busyloop_timeout(struct vhost_dev *dev= , >> + int n, uint32_t timeo= ut) >> +{ >> + int vhost_vq_index =3D dev->vhost_ops->vhost_get_vq_index(dev, n)= ; >> + struct vhost_vring_state state =3D { >> + .index =3D vhost_vq_index, >> + .num =3D timeout, >> + }; >> + int r; >> + >> + if (!dev->vhost_ops->vhost_set_vring_busyloop_timeout) { >> + return -EINVAL; >> + } >> + >> + r =3D dev->vhost_ops->vhost_set_vring_busyloop_timeout(dev, &stat= e); >> + if (r) { >> + return r; >> + } >> + >> + return 0; >> +} >> + >> static int vhost_virtqueue_init(struct vhost_dev *dev, >> struct vhost_virtqueue *vq, int n) >> { >> @@ -994,7 +1016,7 @@ static void vhost_virtqueue_cleanup(struct vhost_= virtqueue *vq) >> } >> =20 >> int vhost_dev_init(struct vhost_dev *hdev, void *opaque, >> - VhostBackendType backend_type) >> + VhostBackendType backend_type, uint32_t busyloop_t= imeout) >> { >> uint64_t features; >> int i, r; >> @@ -1035,6 +1057,17 @@ int vhost_dev_init(struct vhost_dev *hdev, void= *opaque, >> goto fail_vq; >> } >> } >> + >> + if (busyloop_timeout) { >> + for (i =3D 0; i < hdev->nvqs; ++i) { >> + r =3D vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq= _index + i, >> + busyloop_timeout= ); >> + if (r < 0) { >> + goto fail_busyloop; >> + } >> + } >> + } >> + >> hdev->features =3D features; >> =20 >> hdev->memory_listener =3D (MemoryListener) { >> @@ -1077,6 +1110,11 @@ int vhost_dev_init(struct vhost_dev *hdev, void= *opaque, >> hdev->memory_changed =3D false; >> memory_listener_register(&hdev->memory_listener, &address_space_= memory); >> return 0; >> +fail_busyloop: >> + while (--i >=3D 0) { >> + vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i= , 0); >> + } >> + i =3D hdev->nvqs; >> fail_vq: >> while (--i >=3D 0) { >> vhost_virtqueue_cleanup(hdev->vqs + i); >> diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vho= st-backend.h >> index 95fcc96..84e1cb7 100644 >> --- a/include/hw/virtio/vhost-backend.h >> +++ b/include/hw/virtio/vhost-backend.h >> @@ -57,6 +57,8 @@ typedef int (*vhost_set_vring_kick_op)(struct vhost_= dev *dev, >> struct vhost_vring_file *file= ); >> typedef int (*vhost_set_vring_call_op)(struct vhost_dev *dev, >> struct vhost_vring_file *file= ); >> +typedef int (*vhost_set_vring_busyloop_timeout_op)(struct vhost_dev *= dev, >> + struct vhost_vring= _state *r); >> typedef int (*vhost_set_features_op)(struct vhost_dev *dev, >> uint64_t features); >> typedef int (*vhost_get_features_op)(struct vhost_dev *dev, >> @@ -91,6 +93,7 @@ typedef struct VhostOps { >> vhost_get_vring_base_op vhost_get_vring_base; >> vhost_set_vring_kick_op vhost_set_vring_kick; >> vhost_set_vring_call_op vhost_set_vring_call; >> + vhost_set_vring_busyloop_timeout_op vhost_set_vring_busyloop_time= out; >> vhost_set_features_op vhost_set_features; >> vhost_get_features_op vhost_get_features; >> vhost_set_owner_op vhost_set_owner; >> diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h >> index b60d758..2106ed8 100644 >> --- a/include/hw/virtio/vhost.h >> +++ b/include/hw/virtio/vhost.h >> @@ -64,7 +64,8 @@ struct vhost_dev { >> }; >> =20 >> int vhost_dev_init(struct vhost_dev *hdev, void *opaque, >> - VhostBackendType backend_type); >> + VhostBackendType backend_type, >> + uint32_t busyloop_timeout); >> void vhost_dev_cleanup(struct vhost_dev *hdev); >> int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); >> void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); >> diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h >> index 3389b41..8354b98 100644 >> --- a/include/net/vhost_net.h >> +++ b/include/net/vhost_net.h >> @@ -10,6 +10,7 @@ typedef struct vhost_net VHostNetState; >> typedef struct VhostNetOptions { >> VhostBackendType backend_type; >> NetClientState *net_backend; >> + uint32_t busyloop_timeout; >> void *opaque; >> } VhostNetOptions; >> =20 >> diff --git a/net/tap.c b/net/tap.c >> index 740e8a2..7e28102 100644 >> --- a/net/tap.c >> +++ b/net/tap.c >> @@ -663,6 +663,11 @@ static void net_init_tap_one(const NetdevTapOptio= ns *tap, NetClientState *peer, >> =20 >> options.backend_type =3D VHOST_BACKEND_TYPE_KERNEL; >> options.net_backend =3D &s->nc; >> + if (tap->has_vhost_poll_us) { >> + options.busyloop_timeout =3D tap->vhost_poll_us; >> + } else { >> + options.busyloop_timeout =3D 0; >> + } >> =20 >> if (vhostfdname) { >> vhostfd =3D monitor_fd_param(cur_mon, vhostfdname, &err)= ; >> @@ -686,8 +691,9 @@ static void net_init_tap_one(const NetdevTapOption= s *tap, NetClientState *peer, >> "vhost-net requested but could not be initial= ized"); >> return; >> } >> - } else if (vhostfdname) { >> - error_setg(errp, "vhostfd=3D is not valid without vhost"); >> + } else if (vhostfdname || tap->has_vhost_poll_us) { >> + error_setg(errp, "vhostfd(s)=3D or vhost_poll_us=3D is not va= lid" >> + " without vhost"); >> } >> } >> =20 >> diff --git a/net/vhost-user.c b/net/vhost-user.c >> index 1b9e73a..b200182 100644 >> --- a/net/vhost-user.c >> +++ b/net/vhost-user.c >> @@ -80,6 +80,7 @@ static int vhost_user_start(int queues, NetClientSta= te *ncs[]) >> =20 >> options.net_backend =3D ncs[i]; >> options.opaque =3D s->chr; >> + options.busyloop_timeout =3D 0; >> s->vhost_net =3D vhost_net_init(&options); >> if (!s->vhost_net) { >> error_report("failed to init vhost_net for queue %d", i)= ; >> diff --git a/qapi-schema.json b/qapi-schema.json >> index 54634c4..8afdedf 100644 >> --- a/qapi-schema.json >> +++ b/qapi-schema.json >> @@ -2531,6 +2531,9 @@ >> # >> # @queues: #optional number of queues to be created for multiqueue c= apable tap >> # >> +# @vhost-poll-us: #optional maximum number of microseconds that could >> +# be spent on busy polling for vhost net (since 2.7) >> +# >> # Since 1.2 >> ## >> { 'struct': 'NetdevTapOptions', >> @@ -2547,7 +2550,8 @@ >> '*vhostfd': 'str', >> '*vhostfds': 'str', >> '*vhostforce': 'bool', >> - '*queues': 'uint32'} } >> + '*queues': 'uint32', >> + '*vhost-poll-us': 'uint32'} } >> =20 >> ## >> # @NetdevSocketOptions >> diff --git a/qemu-options.hx b/qemu-options.hx >> index 587de8f..22ddb82 100644 >> --- a/qemu-options.hx >> +++ b/qemu-options.hx >> @@ -1569,6 +1569,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, >> "-netdev tap,id=3Dstr[,fd=3Dh][,fds=3Dx:y:...:z][,ifname=3Dname]= [,script=3Dfile][,downscript=3Ddfile]\n" >> " [,helper=3Dhelper][,sndbuf=3Dnbytes][,vnet_hdr=3Don|of= f][,vhost=3Don|off]\n" >> " [,vhostfd=3Dh][,vhostfds=3Dx:y:...:z][,vhostforce=3Don= |off][,queues=3Dn]\n" >> + " [,vhost-poll-us=3Dn]\n" >> " configure a host TAP network backend with ID 's= tr'\n" >> " use network scripts 'file' (default=3D" DEFAULT= _NETWORK_SCRIPT ")\n" >> " to configure it and 'dfile' (default=3D" DEFAUL= T_NETWORK_DOWN_SCRIPT ")\n" >> @@ -1588,6 +1589,8 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, >> " use 'vhostfd=3Dh' to connect to an already open= ed vhost net device\n" >> " use 'vhostfds=3Dx:y:...:z to connect to multipl= e already opened vhost net devices\n" >> " use 'queues=3Dn' to specify the number of queue= s to be created for multiqueue TAP\n" >> + " use 'vhost-poll-us=3Dn' to speciy the maximum nu= mber of microseconds that could be\n" >> + " spent on busy polling for vhost net\n" >> "-netdev bridge,id=3Dstr[,br=3Dbridge][,helper=3Dhelper]\n" >> " configure a host TAP network backend with ID 's= tr' that is\n" >> " connected to a bridge (default=3D" DEFAULT_BRID= GE_INTERFACE ")\n" >> --=20 >> 2.5.0