[libvirt] [PATCH v3 8/9] qemu: Implement chardev hotplug on live level

Michal Privoznik mprivozn at redhat.com
Tue Jul 2 15:53:07 UTC 2013


Since previous patches has prepared everything for us, we may now
implement live hotplug of a character device.
---
 src/qemu/qemu_driver.c  |  18 +++++++-
 src/qemu/qemu_hotplug.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_hotplug.h |   6 +++
 3 files changed, 130 insertions(+), 2 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 6213ab4..df54c64 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6235,6 +6235,13 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
             dev->data.redirdev = NULL;
         break;
 
+    case VIR_DOMAIN_DEVICE_CHR:
+        ret = qemuDomainAttachChrDevice(driver, vm,
+                                        dev->data.chr);
+        if (!ret)
+            dev->data.chr = NULL;
+        break;
+
     default:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("device type '%s' cannot be attached"),
@@ -6322,6 +6329,9 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
     case VIR_DOMAIN_DEVICE_HOSTDEV:
         ret = qemuDomainDetachHostDevice(driver, vm, dev);
         break;
+    case VIR_DOMAIN_DEVICE_CHR:
+        ret = qemuDomainDetachChrDevice(driver, vm, dev->data.chr);
+        break;
     default:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        "%s", _("This type of device cannot be hot unplugged"));
@@ -7022,7 +7032,7 @@ static int qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
     virDomainDefPtr vmdef = NULL;
     virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
     int ret = -1;
-    unsigned int affect;
+    unsigned int affect, parse_flags = 0;
     virQEMUCapsPtr qemuCaps = NULL;
     qemuDomainObjPrivatePtr priv;
     virQEMUDriverConfigPtr cfg = NULL;
@@ -7070,9 +7080,13 @@ static int qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
          goto endjob;
     }
 
+    if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
+        !(flags & VIR_DOMAIN_AFFECT_LIVE))
+        parse_flags |= VIR_DOMAIN_XML_INACTIVE;
+
     dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
                                              caps, driver->xmlopt,
-                                             VIR_DOMAIN_XML_INACTIVE);
+                                             parse_flags);
     if (dev == NULL)
         goto endjob;
 
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 46875ad..af766d0 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1192,6 +1192,67 @@ error:
 
 }
 
+int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
+                              virDomainObjPtr vm,
+                              virDomainChrDefPtr chr)
+{
+    int ret = -1;
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virDomainDefPtr vmdef = vm->def;
+    char *devstr = NULL;
+    char *charAlias = NULL;
+    bool remove = false;
+
+    if (virDomainChrFind(vmdef, chr)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("chardev already exists"));
+        return ret;
+    }
+
+    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("qemu does not support -device"));
+        return ret;
+    }
+
+    if (qemuAssignDeviceChrAlias(vmdef, chr, -1) < 0)
+        return ret;
+
+    if (qemuBuildChrDeviceStr(&devstr, vm->def, chr, priv->qemuCaps) < 0)
+        return ret;
+
+    if (virAsprintf(&charAlias, "char%s", chr->info.alias) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if (virDomainChrInsert(vmdef, chr) < 0)
+        goto cleanup;
+    remove = true;
+
+    qemuDomainObjEnterMonitor(driver, vm);
+    if (qemuMonitorAttachCharDev(priv->mon, charAlias, &chr->source) < 0) {
+        qemuDomainObjExitMonitor(driver, vm);
+        goto cleanup;
+    }
+
+    if (devstr && qemuMonitorAddDevice(priv->mon, devstr) < 0) {
+        /* detach associated chardev on error */
+        qemuMonitorDetachCharDev(priv->mon, charAlias);
+        qemuDomainObjExitMonitor(driver, vm);
+        goto cleanup;
+    }
+    qemuDomainObjExitMonitor(driver, vm);
+
+    ret = 0;
+cleanup:
+    if (ret < 0 && remove)
+        virDomainChrRemove(vmdef, chr);
+    VIR_FREE(charAlias);
+    VIR_FREE(devstr);
+    return ret;
+}
+
 int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
                                   virDomainObjPtr vm,
                                   virDomainHostdevDefPtr hostdev)
@@ -3034,3 +3095,50 @@ int qemuDomainDetachLease(virQEMUDriverPtr driver,
     virDomainLeaseDefFree(det_lease);
     return 0;
 }
+
+int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
+                              virDomainObjPtr vm,
+                              virDomainChrDefPtr chr)
+{
+    int ret = -1;
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virDomainDefPtr vmdef = vm->def;
+    virDomainChrDefPtr tmpChr;
+    char *charAlias = NULL;
+    char *devstr = NULL;
+
+    if (!(tmpChr = virDomainChrFind(vmdef, chr))) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("device not present in domain configuration"));
+        return ret;
+    }
+
+    if (qemuBuildChrDeviceStr(&devstr, vm->def, chr, priv->qemuCaps) < 0)
+        return ret;
+
+    if (virAsprintf(&charAlias, "char%s", tmpChr->info.alias) < 0) {
+        virReportOOMError();
+        return ret;
+    }
+
+    qemuDomainObjEnterMonitor(driver, vm);
+    if (devstr && qemuMonitorDelDevice(priv->mon, tmpChr->info.alias) < 0) {
+        qemuDomainObjExitMonitor(driver, vm);
+        goto cleanup;
+    }
+
+    if (qemuMonitorDetachCharDev(priv->mon, charAlias) < 0) {
+        qemuDomainObjExitMonitor(driver, vm);
+        goto cleanup;
+    }
+    qemuDomainObjExitMonitor(driver, vm);
+
+    virDomainChrRemove(vmdef, tmpChr);
+    virDomainChrDefFree(tmpChr);
+    ret = 0;
+
+cleanup:
+    VIR_FREE(devstr);
+    VIR_FREE(charAlias);
+    return ret;
+}
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index da20eb1..46cd129 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -104,6 +104,12 @@ int qemuDomainAttachLease(virQEMUDriverPtr driver,
 int qemuDomainDetachLease(virQEMUDriverPtr driver,
                           virDomainObjPtr vm,
                           virDomainLeaseDefPtr lease);
+int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
+                              virDomainObjPtr vm,
+                              virDomainChrDefPtr chr);
+int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
+                              virDomainObjPtr vm,
+                              virDomainChrDefPtr chr);
 
 
 #endif /* __QEMU_HOTPLUG_H__ */
-- 
1.8.1.5




More information about the libvir-list mailing list