On Thu, Jul 18, 2013 at 12:03:49PM +0200, Jiri Denemark wrote:
---
Notes:
Version 2:
- DEVICE_DELETED event handler always removes the device
- wait for up to 5 seconds after device_del returns to make
async removal synchronous in normal cases
src/qemu/qemu_domain.c | 4 ++
src/qemu/qemu_domain.h | 3 +
src/qemu/qemu_hotplug.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++--
src/qemu/qemu_hotplug.h | 7 +++
src/qemu/qemu_process.c | 32 ++++++++++
5 files changed, 199 insertions(+), 6 deletions(-)
+static void
+qemuDomainMarkDeviceForRemoval(virDomainObjPtr vm,
+ virDomainDeviceInfoPtr info)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT))
+ priv->unpluggingDevice = info->alias;
+ else
+ priv->unpluggingDevice = NULL;
+}
Ok, this is safe because the callers have locked 'vm'.
+static void
+qemuDomainResetDeviceRemoval(virDomainObjPtr vm)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ priv->unpluggingDevice = NULL;
+}
likewise here
+
+/* Returns:
+ * -1 on error
+ * 0 when DEVICE_DELETED event is unsupported
+ * 1 when device removal finished
+ * 2 device removal did not finish in QEMU_REMOVAL_WAIT_TIME
+ */
+static int
+qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ unsigned long long until;
+
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT))
+ return 0;
+
+ if (virTimeMillisNow(&until) < 0)
+ return -1;
+ until += QEMU_REMOVAL_WAIT_TIME;
+
+ while (priv->unpluggingDevice) {
+ if (virCondWaitUntil(&priv->unplugFinished,
+ &vm->parent.lock, until) < 0) {
+ if (errno == ETIMEDOUT) {
+ return 2;
+ } else {
+ virReportSystemError(errno, "%s",
+ _("Unable to wait on unplug
condition"));
+ return -1;
+ }
+ }
+ }
+
+ return 1;
+}
and virCondWaitUntil is unlocking the 'vm', but this is
safe too, since we're inside a BeginJob block which holds
an extra reference.
+static int
+qemuProcessHandleDeviceDeleted(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm,
+ const char *devAlias)
+{
+ virQEMUDriverPtr driver = qemu_driver;
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+ virDomainDeviceDef dev;
+
+ virObjectLock(vm);
+
+ VIR_DEBUG("Device %s removed from domain %p %s",
+ devAlias, vm, vm->def->name);
+
+ qemuDomainSignalDeviceRemoval(vm, devAlias);
+
+ if (virDomainDefFindDevice(vm->def, devAlias, &dev) < 0)
+ goto cleanup;
+
+ qemuDomainRemoveDevice(driver, vm, &dev);
+
+ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
+ VIR_WARN("unable to save domain status with balloon change");
+
+cleanup:
+ virObjectUnlock(vm);
+ virObjectUnref(cfg);
+ return 0;
+}
Ok, and this holds the lock too. So this all looks correctly synchronized
ACK
Daniel
--
|:
http://berrange.com -o-
http://www.flickr.com/photos/dberrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|:
http://entangle-photo.org -o-
http://live.gnome.org/gtk-vnc :|