summaryrefslogtreecommitdiff
path: root/hw/vhost_net.c
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2011-08-11 10:21:18 +0300
committerMichael S. Tsirkin <mst@redhat.com>2011-08-26 11:25:25 +0300
commitb0b3db79559e57db340b292621c397e7a6cdbdc5 (patch)
tree25519d7db0fa1fe99469b2e10d2423dd69ad6de2 /hw/vhost_net.c
parentc9abe111209abca1b910e35c6ca9888aced5f183 (diff)
vhost-net: cleanup host notifiers at last step
When the vhost notifier is disabled, the userspace handler runs immediately: virtio_pci_set_host_notifier_internal might call virtio_queue_notify_vq. Since the VQ state and the tap backend state aren't recovered yet, this causes "Guest moved used index from XXX to YYY" assertions. The solution is to split out host notifier handling from vhost VQ setup and disable notifiers as our last step when we stop vhost-net. For symmetry enable them first thing on start. Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/vhost_net.c')
-rw-r--r--hw/vhost_net.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
index a55981200d..950a6b8d99 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -139,16 +139,22 @@ int vhost_net_start(struct vhost_net *net,
{
struct vhost_vring_file file = { };
int r;
+
+ net->dev.nvqs = 2;
+ net->dev.vqs = net->vqs;
+
+ r = vhost_dev_enable_notifiers(&net->dev, dev);
+ if (r < 0) {
+ goto fail_notifiers;
+ }
if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
tap_set_vnet_hdr_len(net->vc,
sizeof(struct virtio_net_hdr_mrg_rxbuf));
}
- net->dev.nvqs = 2;
- net->dev.vqs = net->vqs;
r = vhost_dev_start(&net->dev, dev);
if (r < 0) {
- return r;
+ goto fail_start;
}
net->vc->info->poll(net->vc, false);
@@ -173,6 +179,9 @@ fail:
if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr));
}
+fail_start:
+ vhost_dev_disable_notifiers(&net->dev, dev);
+fail_notifiers:
return r;
}
@@ -190,6 +199,7 @@ void vhost_net_stop(struct vhost_net *net,
if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr));
}
+ vhost_dev_disable_notifiers(&net->dev, dev);
}
void vhost_net_cleanup(struct vhost_net *net)