[libvirt] [PATCH v3 03/13] qemu: Reuse qemuDomainDetectVcpuPids in cpu hot(un)plug

Peter Krempa pkrempa at redhat.com
Fri Feb 5 15:44:39 UTC 2016


Now that qemuDomainDetectVcpuPids is able to refresh the vCPU pid
information it can be reused in the hotplug and hotunplug code paths
rather than open-coding a very similar algorithm.

A slight algorithm change is necessary for unplug since the vCPU needs
to be marked offline prior to calling the thread detector function and
eventually rolled back if something fails.
---

Notes:
    v3: correctly handle return values and pointer sanity in the unplug case

 src/qemu/qemu_driver.c | 76 +++++++++++++++++---------------------------------
 1 file changed, 25 insertions(+), 51 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 78f177a..af44b0a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4770,11 +4770,10 @@ qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,
     int ret = -1;
     int rc;
     int oldvcpus = virDomainDefGetVcpus(vm->def);
-    pid_t *cpupids = NULL;
-    int ncpupids = 0;
     virCgroupPtr cgroup_vcpu = NULL;
     char *mem_mask = NULL;
     virDomainNumatuneMemMode mem_mode;
+    pid_t vcpupid;

     if (!(vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu)))
         return -1;
@@ -4789,9 +4788,6 @@ qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,

     rc = qemuMonitorSetCPU(priv->mon, vcpu, true);

-    if (rc == 0)
-        ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids);
-
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;

@@ -4802,23 +4798,15 @@ qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,

     vcpuinfo->online = true;

-    if (ncpupids < 0)
-        goto cleanup;
+    if ((rc = qemuDomainDetectVcpuPids(driver, vm, QEMU_ASYNC_JOB_NONE)) <= 0) {
+        /* vcpu pids were not detected, skip setting of affinity */
+        if (rc == 0)
+            ret = 0;

-    /* failure to re-detect vCPU pids after hotplug due to lack of support was
-     * historically deemed not fatal. We need to skip the rest of the steps though. */
-    if (ncpupids == 0) {
-        ret = 0;
         goto cleanup;
     }

-    if (ncpupids != oldvcpus + 1) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("got wrong number of vCPU pids from QEMU monitor. "
-                         "got %d, wanted %d"),
-                       ncpupids, oldvcpus + 1);
-        goto cleanup;
-    }
+    vcpupid = qemuDomainGetVcpuPid(vm, vcpu);

     if (virDomainNumatuneGetMode(vm->def->numa, -1, &mem_mode) == 0 &&
         mem_mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT &&
@@ -4828,11 +4816,9 @@ qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,
         goto cleanup;

     if (priv->cgroup) {
-        cgroup_vcpu =
-            qemuDomainAddCgroupForThread(priv->cgroup,
-                                         VIR_CGROUP_THREAD_VCPU,
-                                         vcpu, mem_mask,
-                                         cpupids[vcpu]);
+        cgroup_vcpu = qemuDomainAddCgroupForThread(priv->cgroup,
+                                                   VIR_CGROUP_THREAD_VCPU,
+                                                   vcpu, mem_mask, vcpupid);
         if (!cgroup_vcpu)
             goto cleanup;
     }
@@ -4844,26 +4830,20 @@ qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,
                                     &vm->def->cputune.nvcpupin) < 0)
             goto cleanup;

-        if (qemuDomainHotplugPinThread(vm->def->cpumask, vcpu, cpupids[vcpu],
+        if (qemuDomainHotplugPinThread(vm->def->cpumask, vcpu, vcpupid,
                                        cgroup_vcpu) < 0) {
             goto cleanup;
         }
     }

-    if (qemuProcessSetSchedParams(vcpu, cpupids[vcpu],
+    if (qemuProcessSetSchedParams(vcpu, vcpupid,
                                   vm->def->cputune.nvcpusched,
                                   vm->def->cputune.vcpusched) < 0)
         goto cleanup;

-    priv->nvcpupids = ncpupids;
-    VIR_FREE(priv->vcpupids);
-    priv->vcpupids = cpupids;
-    cpupids = NULL;
-
     ret = 0;

  cleanup:
-    VIR_FREE(cpupids);
     VIR_FREE(mem_mask);
     virCgroupFree(&cgroup_vcpu);
     return ret;
@@ -4880,8 +4860,6 @@ qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
     int ret = -1;
     int rc;
     int oldvcpus = virDomainDefGetVcpus(vm->def);
-    pid_t *cpupids = NULL;
-    int ncpupids = 0;

     if (!(vcpuinfo = virDomainDefGetVcpu(vm->def, vcpu)))
         return -1;
@@ -4892,30 +4870,32 @@ qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
         return -1;
     }

+    vcpuinfo->online = false;
+
     qemuDomainObjEnterMonitor(driver, vm);

     rc = qemuMonitorSetCPU(priv->mon, vcpu, false);

-    if (rc == 0)
-        ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids);
-
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;

-    virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update",
-                       rc == 0 && ncpupids == oldvcpus -1);
-
-    if (rc < 0 || ncpupids < 0)
+    if (rc < 0) {
+        virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", false);
+        vcpuinfo->online = true;
         goto cleanup;
+    }

-    /* check if hotunplug has failed */
-    if (ncpupids != oldvcpus - 1) {
-        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
-                       _("qemu didn't unplug vCPU '%u' properly"), vcpu);
+    if ((rc = qemuDomainDetectVcpuPids(driver, vm, QEMU_ASYNC_JOB_NONE)) < 0) {
+        /* rollback only if domain didn't exit */
+        if (rc == -2)
+            goto cleanup;
+
+        virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", false);
+        vcpuinfo->online = true;
         goto cleanup;
     }

-    vcpuinfo->online = false;
+    virDomainAuditVcpu(vm, oldvcpus, oldvcpus - 1, "update", true);

     if (qemuDomainDelCgroupForThread(priv->cgroup,
                                      VIR_CGROUP_THREAD_VCPU, vcpu) < 0)
@@ -4926,15 +4906,9 @@ qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
                     &vm->def->cputune.nvcpupin,
                     vcpu);

-    priv->nvcpupids = ncpupids;
-    VIR_FREE(priv->vcpupids);
-    priv->vcpupids = cpupids;
-    cpupids = NULL;
-
     ret = 0;

  cleanup:
-    VIR_FREE(cpupids);
     return ret;
 }

-- 
2.6.2




More information about the libvir-list mailing list