[libvirt] [PATCH v3 24/24] qemu: hotplug: Add support for VCPU unplug

Peter Krempa pkrempa at redhat.com
Wed Aug 24 13:35:40 UTC 2016


This patch removes the old vcpu unplug code completely and replaces it
with the new code using device_del. The old hotplug code basically never
worked with any recent qemu and thus is useless.

As the new code is using device_del all the implications of using it
are present. Contrary to the device deletion code, the vcpu deletion
code fails if the unplug request is not executed in time.
---
 src/qemu/qemu_driver.c  |  74 ++++++---------------------------
 src/qemu/qemu_hotplug.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_hotplug.h |   7 ++++
 3 files changed, 128 insertions(+), 61 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b531cf5..2248d54 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4061,11 +4061,15 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver,
         goto endjob;
     }

-    if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
-        goto endjob;
+    if (STRPREFIX(devAlias, "vcpu")) {
+        qemuDomainRemoveVcpuAlias(driver, vm, devAlias);
+    } else {
+        if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
+            goto endjob;

-    if (qemuDomainRemoveDevice(driver, vm, &dev) < 0)
-        goto endjob;
+        if (qemuDomainRemoveDevice(driver, vm, &dev) < 0)
+            goto endjob;
+    }

     if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
         VIR_WARN("unable to save domain status after removing device %s",
@@ -4660,60 +4664,6 @@ qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,


 static int
-qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
-                         virDomainObjPtr vm,
-                         unsigned int vcpu)
-{
-    qemuDomainObjPrivatePtr priv = vm->privateData;
-    virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
-    int ret = -1;
-    int rc;
-    int oldvcpus = virDomainDefGetVcpus(vm->def);
-
-    if (!vcpuinfo->online) {
-        virReportError(VIR_ERR_INVALID_ARG,
-                       _("vCPU '%u' is already offline"), vcpu);
-        return -1;
-    }
-
-    vcpuinfo->online = false;
-
-    qemuDomainObjEnterMonitor(driver, vm);
-
-    rc = qemuMonitorSetCPU(priv->mon, vcpu, false);
-
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
-        goto cleanup;
-
-    if (rc < 0) {
-        virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", false);
-        vcpuinfo->online = true;
-        goto cleanup;
-    }
-
-    if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0)
-        goto cleanup;
-
-    if (qemuDomainValidateVcpuInfo(vm) < 0) {
-        /* rollback vcpu count if the setting has failed */
-        virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", false);
-        vcpuinfo->online = true;
-        goto cleanup;
-    }
-
-    virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", true);
-
-    if (virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, vcpu) < 0)
-        goto cleanup;
-
-    ret = 0;
-
- cleanup:
-    return ret;
-}
-
-
-static int
 qemuDomainSetVcpusAgent(virDomainObjPtr vm,
                         unsigned int nvcpus)
 {
@@ -4888,7 +4838,6 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
                        unsigned int nvcpus)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
-    size_t i;
     virCgroupPtr cgroup_temp = NULL;
     char *mem_mask = NULL;
     char *all_nodes_str = NULL;
@@ -4925,8 +4874,11 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
                 break;
         }
     } else {
-        for (i = virDomainDefGetVcpus(vm->def) - 1; i >= nvcpus; i--) {
-            if ((rc = qemuDomainHotplugDelVcpu(driver, vm, i)) < 0)
+        for (nextvcpu = virDomainDefGetVcpusMax(vm->def) - 1; nextvcpu >= 0; nextvcpu--) {
+            if (!virBitmapIsBitSet(vcpumap, nextvcpu))
+                continue;
+
+            if ((rc = qemuDomainHotplugDelVcpu(driver, vm, nextvcpu)) < 0)
                 break;
         }
     }
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 31ef22f..1bdde5b 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -4419,3 +4419,111 @@ qemuDomainDetachMemoryDevice(virQEMUDriverPtr driver,
     qemuDomainResetDeviceRemoval(vm);
     return ret;
 }
+
+
+static int
+qemuDomainRemoveVcpu(virQEMUDriverPtr driver,
+                     virDomainObjPtr vm,
+                     unsigned int vcpu)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
+    qemuDomainVcpuPrivatePtr vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
+    int oldvcpus = virDomainDefGetVcpus(vm->def);
+    unsigned int nvcpus = vcpupriv->vcpus;
+    size_t i;
+
+    if (qemuDomainRefreshVcpuInfo(driver, vm, QEMU_ASYNC_JOB_NONE, false) < 0)
+        return -1;
+
+    /* validation requires us to set the expected state prior to calling it */
+    for (i = vcpu; i < vcpu + nvcpus; i++) {
+        vcpuinfo = virDomainDefGetVcpu(vm->def, i);
+        vcpuinfo->online = false;
+    }
+
+    if (qemuDomainValidateVcpuInfo(vm) < 0) {
+        /* rollback vcpu count if the setting has failed */
+        virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false);
+
+        for (i = vcpu; i < vcpu + nvcpus; i++) {
+            vcpuinfo = virDomainDefGetVcpu(vm->def, i);
+            vcpuinfo->online = true;
+        }
+        return -1;
+    }
+
+    virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", true);
+
+    for (i = vcpu; i < vcpu + nvcpus; i++) {
+        vcpuinfo = virDomainDefGetVcpu(vm->def, i);
+        if (virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+
+void
+qemuDomainRemoveVcpuAlias(virQEMUDriverPtr driver,
+                          virDomainObjPtr vm,
+                          const char *alias)
+{
+    virDomainVcpuDefPtr vcpu;
+    qemuDomainVcpuPrivatePtr vcpupriv;
+    size_t i;
+
+    for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
+        vcpu = virDomainDefGetVcpu(vm->def, i);
+        vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
+
+        if (STREQ_NULLABLE(alias, vcpupriv->alias)) {
+            qemuDomainRemoveVcpu(driver, vm, i);
+            return;
+        }
+    }
+}
+
+
+int
+qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
+                         virDomainObjPtr vm,
+                         unsigned int vcpu)
+{
+    virDomainVcpuDefPtr vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu);
+    qemuDomainVcpuPrivatePtr vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpuinfo);
+    int oldvcpus = virDomainDefGetVcpus(vm->def);
+    unsigned int nvcpus = vcpupriv->vcpus;
+    int rc;
+
+    if (!vcpupriv->alias) {
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+                       _("vcpu '%u' can't be unplugged"), vcpu);
+        return -1;
+    }
+
+    qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias);
+
+    qemuDomainObjEnterMonitor(driver, vm);
+
+    rc = qemuMonitorDelDevice(qemuDomainGetMonitor(vm), vcpupriv->alias);
+
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        return -1;
+
+    if (rc < 0) {
+        virDomainAuditVcpu(vm, oldvcpus, oldvcpus - nvcpus, "update", false);
+        return -1;
+    }
+
+    if ((rc = qemuDomainWaitForDeviceRemoval(vm)) <= 0) {
+        if (rc == 0)
+            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                           _("vcpu unplug request timed out"));
+
+        return -1;
+    }
+
+    return qemuDomainRemoveVcpu(driver, vm, vcpu);
+}
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index 165d345..b048cf4 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -105,6 +105,13 @@ int qemuDomainDetachRNGDevice(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
                               virDomainRNGDefPtr rng);

+int qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
+                             virDomainObjPtr vm,
+                             unsigned int vcpu);
+void qemuDomainRemoveVcpuAlias(virQEMUDriverPtr driver,
+                               virDomainObjPtr vm,
+                               const char *alias);
+
 int
 qemuDomainChrInsert(virDomainDefPtr vmdef,
                     virDomainChrDefPtr chr);
-- 
2.8.2




More information about the libvir-list mailing list