Blame SOURCES/libvirt-qemu-cgroup-Extract-temporary-relaxing-of-cgroup-setting-for-vcpu-hotplug.patch

6ae9ed
From b858c92c39a76d6a4aedea05b4f9bf801055f824 Mon Sep 17 00:00:00 2001
6ae9ed
Message-Id: <b858c92c39a76d6a4aedea05b4f9bf801055f824@dist-git>
6ae9ed
From: Peter Krempa <pkrempa@redhat.com>
6ae9ed
Date: Wed, 7 Sep 2016 16:12:13 +0200
6ae9ed
Subject: [PATCH] qemu: cgroup: Extract temporary relaxing of cgroup setting
6ae9ed
 for vcpu hotplug
6ae9ed
6ae9ed
https://bugzilla.redhat.com/show_bug.cgi?id=1097930
6ae9ed
6ae9ed
When hot-adding vcpus qemu needs to allocate some structures in the DMA
6ae9ed
zone which may be outside of the numa pinning. Extract the code doing
6ae9ed
this in a set of helpers so that it can be reused.
6ae9ed
6ae9ed
(cherry picked from commit eb5dee353479629d8769de0cfe77c59711c70d79)
6ae9ed
---
6ae9ed
 src/qemu/qemu_cgroup.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++
6ae9ed
 src/qemu/qemu_cgroup.h | 11 ++++++
6ae9ed
 src/qemu/qemu_driver.c | 36 +++-----------------
6ae9ed
 3 files changed, 105 insertions(+), 32 deletions(-)
6ae9ed
6ae9ed
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
6ae9ed
index 2dca874..e2b5bab 100644
6ae9ed
--- a/src/qemu/qemu_cgroup.c
6ae9ed
+++ b/src/qemu/qemu_cgroup.c
6ae9ed
@@ -1127,3 +1127,93 @@ qemuRemoveCgroup(virDomainObjPtr vm)
6ae9ed
 
6ae9ed
     return virCgroupRemove(priv->cgroup);
6ae9ed
 }
6ae9ed
+
6ae9ed
+
6ae9ed
+static void
6ae9ed
+qemuCgroupEmulatorAllNodesDataFree(qemuCgroupEmulatorAllNodesDataPtr data)
6ae9ed
+{
6ae9ed
+    if (!data)
6ae9ed
+        return;
6ae9ed
+
6ae9ed
+    virCgroupFree(&data->emulatorCgroup);
6ae9ed
+    VIR_FREE(data->emulatorMemMask);
6ae9ed
+    VIR_FREE(data);
6ae9ed
+}
6ae9ed
+
6ae9ed
+
6ae9ed
+/**
6ae9ed
+ * qemuCgroupEmulatorAllNodesAllow:
6ae9ed
+ * @cgroup: domain cgroup pointer
6ae9ed
+ * @retData: filled with structure used to roll back the operation
6ae9ed
+ *
6ae9ed
+ * Allows all NUMA nodes for the qemu emulator thread temporarily. This is
6ae9ed
+ * necessary when hotplugging cpus since it requires memory allocated in the
6ae9ed
+ * DMA region. Afterwards the operation can be reverted by
6ae9ed
+ * qemuCgrouEmulatorAllNodesRestore.
6ae9ed
+ *
6ae9ed
+ * Returns 0 on success -1 on error
6ae9ed
+ */
6ae9ed
+int
6ae9ed
+qemuCgroupEmulatorAllNodesAllow(virCgroupPtr cgroup,
6ae9ed
+                                qemuCgroupEmulatorAllNodesDataPtr *retData)
6ae9ed
+{
6ae9ed
+    qemuCgroupEmulatorAllNodesDataPtr data = NULL;
6ae9ed
+    char *all_nodes_str = NULL;
6ae9ed
+    virBitmapPtr all_nodes = NULL;
6ae9ed
+    int ret = -1;
6ae9ed
+
6ae9ed
+    if (!virNumaIsAvailable() ||
6ae9ed
+        !virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_CPUSET))
6ae9ed
+        return 0;
6ae9ed
+
6ae9ed
+    if (!(all_nodes = virNumaGetHostNodeset()))
6ae9ed
+        goto cleanup;
6ae9ed
+
6ae9ed
+    if (!(all_nodes_str = virBitmapFormat(all_nodes)))
6ae9ed
+        goto cleanup;
6ae9ed
+
6ae9ed
+    if (VIR_ALLOC(data) < 0)
6ae9ed
+        goto cleanup;
6ae9ed
+
6ae9ed
+    if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
6ae9ed
+                           false, &data->emulatorCgroup) < 0)
6ae9ed
+        goto cleanup;
6ae9ed
+
6ae9ed
+    if (virCgroupGetCpusetMems(data->emulatorCgroup, &data->emulatorMemMask) < 0 ||
6ae9ed
+        virCgroupSetCpusetMems(data->emulatorCgroup, all_nodes_str) < 0)
6ae9ed
+        goto cleanup;
6ae9ed
+
6ae9ed
+    VIR_STEAL_PTR(*retData, data);
6ae9ed
+    ret = 0;
6ae9ed
+
6ae9ed
+ cleanup:
6ae9ed
+    VIR_FREE(all_nodes_str);
6ae9ed
+    virBitmapFree(all_nodes);
6ae9ed
+    qemuCgroupEmulatorAllNodesDataFree(data);
6ae9ed
+
6ae9ed
+    return ret;
6ae9ed
+}
6ae9ed
+
6ae9ed
+
6ae9ed
+/**
6ae9ed
+ * qemuCgrouEmulatorAllNodesRestore:
6ae9ed
+ * @data: data structure created by qemuCgroupEmulatorAllNodesAllow
6ae9ed
+ *
6ae9ed
+ * Rolls back the setting done by qemuCgroupEmulatorAllNodesAllow and frees the
6ae9ed
+ * associated data.
6ae9ed
+ */
6ae9ed
+void
6ae9ed
+qemuCgrouEmulatorAllNodesRestore(qemuCgroupEmulatorAllNodesDataPtr data)
6ae9ed
+{
6ae9ed
+    virErrorPtr err;
6ae9ed
+
6ae9ed
+    if (!data)
6ae9ed
+        return;
6ae9ed
+
6ae9ed
+    err = virSaveLastError();
6ae9ed
+    virCgroupSetCpusetMems(data->emulatorCgroup, data->emulatorMemMask);
6ae9ed
+    virSetError(err);
6ae9ed
+    virFreeError(err);
6ae9ed
+
6ae9ed
+    qemuCgroupEmulatorAllNodesDataFree(data);
6ae9ed
+}
6ae9ed
diff --git a/src/qemu/qemu_cgroup.h b/src/qemu/qemu_cgroup.h
6ae9ed
index dc340a1..e6ebae0 100644
6ae9ed
--- a/src/qemu/qemu_cgroup.h
6ae9ed
+++ b/src/qemu/qemu_cgroup.h
6ae9ed
@@ -57,4 +57,15 @@ int qemuSetupCgroupCpusetCpus(virCgroupPtr cgroup, virBitmapPtr cpumask);
6ae9ed
 int qemuSetupGlobalCpuCgroup(virDomainObjPtr vm);
6ae9ed
 int qemuRemoveCgroup(virDomainObjPtr vm);
6ae9ed
 
6ae9ed
+typedef struct _qemuCgroupEmulatorAllNodesData qemuCgroupEmulatorAllNodesData;
6ae9ed
+typedef qemuCgroupEmulatorAllNodesData *qemuCgroupEmulatorAllNodesDataPtr;
6ae9ed
+struct _qemuCgroupEmulatorAllNodesData {
6ae9ed
+    virCgroupPtr emulatorCgroup;
6ae9ed
+    char *emulatorMemMask;
6ae9ed
+};
6ae9ed
+
6ae9ed
+int qemuCgroupEmulatorAllNodesAllow(virCgroupPtr cgroup,
6ae9ed
+                                    qemuCgroupEmulatorAllNodesDataPtr *data);
6ae9ed
+void qemuCgrouEmulatorAllNodesRestore(qemuCgroupEmulatorAllNodesDataPtr data);
6ae9ed
+
6ae9ed
 #endif /* __QEMU_CGROUP_H__ */
6ae9ed
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
6ae9ed
index 33bfb67..6775327 100644
6ae9ed
--- a/src/qemu/qemu_driver.c
6ae9ed
+++ b/src/qemu/qemu_driver.c
6ae9ed
@@ -4859,11 +4859,7 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
6ae9ed
                        unsigned int nvcpus)
6ae9ed
 {
6ae9ed
     qemuDomainObjPrivatePtr priv = vm->privateData;
6ae9ed
-    virCgroupPtr cgroup_temp = NULL;
6ae9ed
-    char *mem_mask = NULL;
6ae9ed
-    char *all_nodes_str = NULL;
6ae9ed
-    virBitmapPtr all_nodes = NULL;
6ae9ed
-    virErrorPtr err = NULL;
6ae9ed
+    qemuCgroupEmulatorAllNodesDataPtr emulatorCgroup = NULL;
6ae9ed
     virBitmapPtr vcpumap = NULL;
6ae9ed
     ssize_t nextvcpu = -1;
6ae9ed
     int rc = 0;
6ae9ed
@@ -4872,22 +4868,8 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
6ae9ed
     if (!(vcpumap = qemuDomainSelectHotplugVcpuEntities(vm->def, nvcpus)))
6ae9ed
         goto cleanup;
6ae9ed
 
6ae9ed
-    if (virNumaIsAvailable() &&
6ae9ed
-        virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
6ae9ed
-        if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
6ae9ed
-                               false, &cgroup_temp) < 0)
6ae9ed
-            goto cleanup;
6ae9ed
-
6ae9ed
-        if (!(all_nodes = virNumaGetHostNodeset()))
6ae9ed
-            goto cleanup;
6ae9ed
-
6ae9ed
-        if (!(all_nodes_str = virBitmapFormat(all_nodes)))
6ae9ed
-            goto cleanup;
6ae9ed
-
6ae9ed
-        if (virCgroupGetCpusetMems(cgroup_temp, &mem_mask) < 0 ||
6ae9ed
-            virCgroupSetCpusetMems(cgroup_temp, all_nodes_str) < 0)
6ae9ed
-            goto cleanup;
6ae9ed
-    }
6ae9ed
+    if (qemuCgroupEmulatorAllNodesAllow(priv->cgroup, &emulatorCgroup) < 0)
6ae9ed
+        goto cleanup;
6ae9ed
 
6ae9ed
     if (nvcpus > virDomainDefGetVcpus(vm->def)) {
6ae9ed
         while ((nextvcpu = virBitmapNextSetBit(vcpumap, nextvcpu)) != -1) {
6ae9ed
@@ -4915,17 +4897,7 @@ qemuDomainSetVcpusLive(virQEMUDriverPtr driver,
6ae9ed
     ret = 0;
6ae9ed
 
6ae9ed
  cleanup:
6ae9ed
-    if (mem_mask) {
6ae9ed
-        err = virSaveLastError();
6ae9ed
-        virCgroupSetCpusetMems(cgroup_temp, mem_mask);
6ae9ed
-        virSetError(err);
6ae9ed
-        virFreeError(err);
6ae9ed
-        VIR_FREE(mem_mask);
6ae9ed
-    }
6ae9ed
-
6ae9ed
-    VIR_FREE(all_nodes_str);
6ae9ed
-    virBitmapFree(all_nodes);
6ae9ed
-    virCgroupFree(&cgroup_temp);
6ae9ed
+    qemuCgrouEmulatorAllNodesRestore(emulatorCgroup);
6ae9ed
     virBitmapFree(vcpumap);
6ae9ed
 
6ae9ed
     return ret;
6ae9ed
-- 
6ae9ed
2.10.0
6ae9ed