Message ID | 1409670380-22943-14-git-send-email-mst@redhat.com |
---|---|
State | New |
Headers | show |
On Sep02 18:07, Michael S. Tsirkin wrote: > From: Jason Wang <jasowang@redhat.com> > > 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)" <zhangjie14@huawei.com> > Tested-by: William Dauchy <wdauchy@gmail.com> please use: Tested-by: William Dauchy <william@gandi.net> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com> > Signed-off-by: Jason Wang <jasowang@redhat.com> > Reviewed-by: Michael S. Tsirkin <mst@redhat.com> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Thanks,
On Tue, Sep 02, 2014 at 05:47:54PM +0200, William Dauchy wrote: > On Sep02 18:07, Michael S. Tsirkin wrote: > > From: Jason Wang <jasowang@redhat.com> > > > > 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)" <zhangjie14@huawei.com> > > Tested-by: William Dauchy <wdauchy@gmail.com> > > please use: > > Tested-by: William Dauchy <william@gandi.net> It's a pull request so not easy to fix. I'll do it like that next time. > > Signed-off-by: Michael S. Tsirkin <mst@redhat.com> > > Signed-off-by: Jason Wang <jasowang@redhat.com> > > Reviewed-by: Michael S. Tsirkin <mst@redhat.com> > > Signed-off-by: Michael S. Tsirkin <mst@redhat.com> > > Thanks, > -- > William
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) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index e55fe1c..5d7c40a 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -976,7 +976,6 @@ void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev) bool vhost_virtqueue_pending(struct vhost_dev *hdev, int n) { struct vhost_virtqueue *vq = hdev->vqs + n - hdev->vq_index; - assert(hdev->started); assert(n >= hdev->vq_index && n < hdev->vq_index + hdev->nvqs); return event_notifier_test_and_clear(&vq->masked_notifier); } @@ -988,7 +987,6 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, struct VirtQueue *vvq = virtio_get_queue(vdev, n); int r, index = n - hdev->vq_index; - assert(hdev->started); assert(n >= hdev->vq_index && n < hdev->vq_index + hdev->nvqs); struct vhost_vring_file file = {