vhost: fix cleanup on not fully initialized device

If vhost_dev_init() failed, caller may still call vhost_dev_cleanup()
later. However, vhost_dev_cleanup() tries to remove the device from the
list even if it wasn't yet added, which may lead to crashes. Similarly
for the memory listener.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
master
Marc-André Lureau 2016-07-27 01:15:01 +04:00 committed by Michael S. Tsirkin
parent 7b527247f0
commit 5be5f9be72
1 changed files with 6 additions and 3 deletions

View File

@ -1033,7 +1033,6 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
r = -1;
goto fail;
}
QLIST_INSERT_HEAD(&vhost_devices, hdev, entry);
r = hdev->vhost_ops->vhost_set_owner(hdev);
if (r < 0) {
@ -1103,6 +1102,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
hdev->started = false;
hdev->memory_changed = false;
memory_listener_register(&hdev->memory_listener, &address_space_memory);
QLIST_INSERT_HEAD(&vhost_devices, hdev, entry);
return 0;
fail_busyloop:
while (--i >= 0) {
@ -1126,7 +1126,11 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
for (i = 0; i < hdev->nvqs; ++i) {
vhost_virtqueue_cleanup(hdev->vqs + i);
}
memory_listener_unregister(&hdev->memory_listener);
if (hdev->mem) {
/* those are only safe after successful init */
memory_listener_unregister(&hdev->memory_listener);
QLIST_REMOVE(hdev, entry);
}
if (hdev->migration_blocker) {
migrate_del_blocker(hdev->migration_blocker);
error_free(hdev->migration_blocker);
@ -1135,7 +1139,6 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
g_free(hdev->mem_sections);
hdev->vhost_ops->vhost_backend_cleanup(hdev);
assert(!hdev->log);
QLIST_REMOVE(hdev, entry);
}
/* Stop processing guest IO notifications in qemu.