From 2d2507ef23d2a28eaeea5507ff4ec68657f1792f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 4 Aug 2014 14:12:39 +0200 Subject: vhost_net: cleanup start/stop condition Checking vhost device internal state in vhost_net looks like a layering violation since vhost_net does not set this flag: it is set and tested by vhost.c. There seems to be no reason to check this: caller in virtio net uses its own flag, vhost_started, to ensure vhost is started/stopped as appropriate. Signed-off-by: Michael S. Tsirkin Reviewed-by: Amos Kong --- hw/net/vhost_net.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'hw/net') diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index f87c798..9bbf2ee 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -195,10 +195,6 @@ static int vhost_net_start_one(struct vhost_net *net, struct vhost_vring_file file = { }; int r; - if (net->dev.started) { - return 0; - } - net->dev.nvqs = 2; net->dev.vqs = net->vqs; net->dev.vq_index = vq_index; @@ -256,10 +252,6 @@ static void vhost_net_stop_one(struct vhost_net *net, { struct vhost_vring_file file = { .fd = -1 }; - if (!net->dev.started) { - return; - } - if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { const VhostOps *vhost_ops = net->dev.vhost_ops; -- cgit v1.1 From 0187c7989a5cedd4f88bba76839cc9c44fb3fc81 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 2 Sep 2014 16:12:41 +0300 Subject: virtio-net: don't run bh on vm stopped commit 783e7706937fe15523b609b545587a028a2bdd03 virtio-net: stop/start bh when appropriate is incomplete: BH might execute within the same main loop iteration but after vmstop, so in theory, we might trigger an assertion. I was unable to reproduce this in practice, but it seems clear enough that the potential is there, so worth fixing. Cc: qemu-stable@nongnu.org Reported-by: Stefan Hajnoczi Signed-off-by: Michael S. Tsirkin --- hw/net/virtio-net.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'hw/net') diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 268eff9..365e266 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -1224,7 +1224,12 @@ static void virtio_net_tx_timer(void *opaque) VirtIONetQueue *q = opaque; VirtIONet *n = q->n; VirtIODevice *vdev = VIRTIO_DEVICE(n); - assert(vdev->vm_running); + /* This happens when device was stopped but BH wasn't. */ + if (!vdev->vm_running) { + /* Make sure tx waiting is set, so we'll run when restarted. */ + assert(q->tx_waiting); + return; + } q->tx_waiting = 0; @@ -1244,7 +1249,12 @@ static void virtio_net_tx_bh(void *opaque) VirtIODevice *vdev = VIRTIO_DEVICE(n); int32_t ret; - assert(vdev->vm_running); + /* This happens when device was stopped but BH wasn't. */ + if (!vdev->vm_running) { + /* Make sure tx waiting is set, so we'll run when restarted. */ + assert(q->tx_waiting); + return; + } q->tx_waiting = 0; -- cgit v1.1 From aad4dce934649b3a398396fc2a76f215bb194ea4 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 19 Aug 2014 12:56:29 +0800 Subject: vhost_net: start/stop guest notifiers properly commit a9f98bb5ebe6fb1869321dcc58e72041ae626ad8 vhost: multiqueue support changed the order of stopping the device. Previously vhost_dev_stop would disable backend and only afterwards, unset guest notifiers. We now unset guest notifiers while vhost is still active. This can lose interrupts causing guest networking to fail. In particular, this has been observed during migration. To adapt this, several other changes are needed: - remove the hdev->started assertion in vhost.c since we may want to start the guest notifiers before vhost starts and stop the guest notifiers after vhost is stopped. - introduce the vhost_net_set_vq_index() and call it before setting guest notifiers. This is used to guarantee vhost_net has the correct virtqueue index when setting guest notifiers. Cc: qemu-stable@nongnu.org Reported-by: "Zhangjie (HZ)" Tested-by: William Dauchy Signed-off-by: Michael S. Tsirkin Signed-off-by: Jason Wang Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/net/vhost_net.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'hw/net') diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 9bbf2ee..ba5d544 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -188,16 +188,19 @@ bool vhost_net_query(VHostNetState *net, VirtIODevice *dev) return vhost_dev_query(&net->dev, dev); } +static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index) +{ + net->dev.vq_index = vq_index; +} + static int vhost_net_start_one(struct vhost_net *net, - VirtIODevice *dev, - int vq_index) + VirtIODevice *dev) { struct vhost_vring_file file = { }; int r; net->dev.nvqs = 2; net->dev.vqs = net->vqs; - net->dev.vq_index = vq_index; r = vhost_dev_enable_notifiers(&net->dev, dev); if (r < 0) { @@ -301,11 +304,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, } for (i = 0; i < total_queues; i++) { - r = vhost_net_start_one(get_vhost_net(ncs[i].peer), dev, i * 2); - - if (r < 0) { - goto err; - } + vhost_net_set_vq_index(get_vhost_net(ncs[i].peer), i * 2); } r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true); @@ -314,6 +313,14 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, goto err; } + for (i = 0; i < total_queues; i++) { + r = vhost_net_start_one(get_vhost_net(ncs[i].peer), dev); + + if (r < 0) { + goto err; + } + } + return 0; err: @@ -331,16 +338,16 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs, VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); int i, r; + for (i = 0; i < total_queues; i++) { + vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); + } + r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false); if (r < 0) { fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r); fflush(stderr); } assert(r >= 0); - - for (i = 0; i < total_queues; i++) { - vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); - } } void vhost_net_cleanup(struct vhost_net *net) -- cgit v1.1