From 9c3d2d957347dc8f6d71e5ba13f2ef6b02dd8401 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin <markmc@redhat.com> Date: Fri, 15 May 2009 12:32:57 +0100 Subject: [PATCH 11/16] Fix virtio-net segfault during live migrate after NIC hot-unplug https://bugzilla.redhat.com/500975 virtio-net registers a savevm handler which is not removed when the NIC is hot-unplugged. First part of this fix backports unregister_savevm() from: http://git.kernel.org/?p=virt/kvm/qemu-kvm.git;a=commitdiff;h=00f56b3dcf and the second part cherry-picks virtio_net_cleanup() from: http://git.kernel.org/?p=virt/kvm/qemu-kvm.git;a=commitdiff;h=a34b6eb776 Signed-off-by: Mark McLoughlin <markmc@redhat.com> Message-Id: <1242387177.25932.6.camel@blaa> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> Bugzilla: 501729 RH-Upstream-status: applied(qemu-kvm/master) Acked-by: Glauber Costa <glommer@redhat.com> Depends: <1242387172.25932.5.camel@blaa> Acked-by: Eduardo Habkost <ehabkost@redhat.com> Acked-by: Kevin Wolf <kwolf@redhat.com> Acked-by: Juan Quintela <quintela@redhat.com> --- qemu/hw/hw.h | 2 ++ qemu/hw/virtio-net.c | 13 +++++++++++++ qemu/hw/virtio.c | 7 +++++++ qemu/hw/virtio.h | 2 ++ qemu/savevm.c | 16 ++++++++++++++++ 5 files changed, 40 insertions(+), 0 deletions(-) diff --git a/qemu/hw/hw.h b/qemu/hw/hw.h index 6aad964..2d3ce4c 100644 --- a/qemu/hw/hw.h +++ b/qemu/hw/hw.h @@ -239,6 +239,8 @@ int register_savevm_live(const char *idstr, LoadStateHandler *load_state, void *opaque); +void unregister_savevm(const char *idstr, void *opaque); + typedef void QEMUResetHandler(void *opaque); void qemu_register_reset(QEMUResetHandler *func, void *opaque); diff --git a/qemu/hw/virtio-net.c b/qemu/hw/virtio-net.c index 0edc8e3..07c7f76 100644 --- a/qemu/hw/virtio-net.c +++ b/qemu/hw/virtio-net.c @@ -424,6 +424,18 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) return 0; } +static void virtio_net_cleanup(VLANClientState *vc) +{ + VirtIONet *n = vc->opaque; + + unregister_savevm("virtio-net", n); + + qemu_del_timer(n->tx_timer); + qemu_free_timer(n->tx_timer); + + virtio_cleanup(&n->vdev); +} + PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn) { VirtIONet *n; @@ -450,6 +462,7 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn) n->status = VIRTIO_NET_S_LINK_UP; n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, virtio_net_receive, virtio_net_can_receive, n); + n->vc->cleanup = virtio_net_cleanup; n->vc->link_status_changed = virtio_net_set_link_status; qemu_format_nic_info_str(n->vc, n->mac); diff --git a/qemu/hw/virtio.c b/qemu/hw/virtio.c index 198cc72..2fdfc59 100644 --- a/qemu/hw/virtio.c +++ b/qemu/hw/virtio.c @@ -815,6 +815,13 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f) virtio_update_irq(vdev); } +void virtio_cleanup(VirtIODevice *vdev) +{ + if (vdev->config) + qemu_free(vdev->config); + qemu_free(vdev->vq); +} + VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name, uint16_t vendor, uint16_t device, uint16_t subvendor, uint16_t subdevice, diff --git a/qemu/hw/virtio.h b/qemu/hw/virtio.h index 3c190dd..9500fd6 100644 --- a/qemu/hw/virtio.h +++ b/qemu/hw/virtio.h @@ -118,6 +118,8 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f); void virtio_load(VirtIODevice *vdev, QEMUFile *f); +void virtio_cleanup(VirtIODevice *vdev); + void virtio_notify_config(VirtIODevice *vdev); void virtio_queue_set_notification(VirtQueue *vq, int enable); diff --git a/qemu/savevm.c b/qemu/savevm.c index 547a972..9694c9b 100644 --- a/qemu/savevm.c +++ b/qemu/savevm.c @@ -658,6 +658,22 @@ int register_savevm(const char *idstr, NULL, save_state, load_state, opaque); } +void unregister_savevm(const char *idstr, void *opaque) +{ + SaveStateEntry **pse; + + pse = &first_se; + while (*pse != NULL) { + if (strcmp((*pse)->idstr, idstr) == 0 && (*pse)->opaque == opaque) { + SaveStateEntry *next = (*pse)->next; + qemu_free(*pse); + *pse = next; + continue; + } + pse = &(*pse)->next; + } +} + #define QEMU_VM_FILE_MAGIC 0x5145564d #define QEMU_VM_FILE_VERSION_COMPAT 0x00000002 #define QEMU_VM_FILE_VERSION 0x00000003 -- 1.6.3.rc4.29.g8146