From 655429a0d4a51e7deb533e1d17c1a41360ad2965 Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Tue, 29 Nov 2016 22:40:16 +0100 Subject: [PATCH] qemu: Prevent detaching SCSI controller used by hostdev Consider the following XML snippets: $ cat scsicontroller.xml $ cat scsihostdev.xml
If we create a guest that includes the contents of scsihostdev.xml, but forget the virtio-scsi controller described in scsicontroller.xml, one is silently created for us. The same holds true when attaching a hostdev before the matching virtio-scsi controller. (See qemuDomainFindOrCreateSCSIDiskController for context.) Detaching the hostdev, followed by the controller, works well and the guest behaves appropriately. If we detach the virtio-scsi controller device first, any associated hostdevs are detached for us by the underlying virtio-scsi code (this is fine, since the connection is broken). But all is not well, as the guest is unable to receive new virtio-scsi devices (the attach commands succeed, but devices never appear within the guest), nor even be shutdown, after this point. While this is not libvirt's problem, we can prevent falling into this scenario by checking if a controller is being used by any hostdev devices. The same is already done for disk elements today. Applying this patch and then using the XML snippets from earlier: $ virsh detach-device guest_01 scsicontroller.xml error: Failed to detach device from scsicontroller.xml error: operation failed: device cannot be detached: device is busy $ virsh detach-device guest_01 scsihostdev.xml Device detached successfully $ virsh detach-device guest_01 scsicontroller.xml Device detached successfully Signed-off-by: Eric Farman Reviewed-by: Bjoern Walk Reviewed-by: Boris Fiuczynski --- src/qemu/qemu_hotplug.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 9d74dfb15d..7c3f32d7a6 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -4444,6 +4444,7 @@ static bool qemuDomainDiskControllerIsBusy(virDomainObjPtr vm, { size_t i; virDomainDiskDefPtr disk; + virDomainHostdevDefPtr hostdev; for (i = 0; i < vm->def->ndisks; i++) { disk = vm->def->disks[i]; @@ -4466,6 +4467,15 @@ static bool qemuDomainDiskControllerIsBusy(virDomainObjPtr vm, return true; } + for (i = 0; i < vm->def->nhostdevs; i++) { + hostdev = vm->def->hostdevs[i]; + if (!virHostdevIsSCSIDevice(hostdev) || + detach->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI) + continue; + if (hostdev->info->addr.drive.controller == detach->idx) + return true; + } + return false; }