]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: hotplug: Add support for VCPU unplug
authorPeter Krempa <pkrempa@redhat.com>
Tue, 16 Aug 2016 13:02:11 +0000 (15:02 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Wed, 24 Aug 2016 19:44:47 +0000 (15:44 -0400)
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
src/qemu/qemu_hotplug.c
src/qemu/qemu_hotplug.h

index 69d38ecc62028679b33982706c2fb9499ae5d4d4..97e2ffc404ab9402c43b93e11cd92f33324ce0b0 100644 (file)
@@ -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",
@@ -4659,60 +4663,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)
@@ -4889,7 +4839,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;
@@ -4926,8 +4875,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;
         }
     }
index 31ef22f7e2b6deed414ed0c01f110c24d4f17bd7..1bdde5bed6ba4ce5193b3f83ff4f20814a8fef76 100644 (file)
@@ -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);
+}
index 165d345bbcbd3c0ff63bf983a1d743d2e36ac2cc..b048cf4688a4de041d50ba392b2e0bcdcdf5434d 100644 (file)
@@ -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);