]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Explicitly forbid live changing nodeset for strict numatune
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 15 Dec 2021 13:20:21 +0000 (14:20 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 17 Dec 2021 12:21:48 +0000 (13:21 +0100)
Let's imagine a guest that's configured with strict numatune:

  <numatune>
    <memory mode='strict' nodeset='0'/>
  </numatune>

For guests with NUMA:
Depending on machine type used (see commit v6.4.0-rc1~75) we
generate either:

  1) -object '{"qom-type":"memory-backend-ram","id":"ram-node0",\
               "size":20971520,"host-nodes":[0],"policy":"preferred"}' \
     -numa node,nodeid=0,cpus=0,memdev=ram-node0

or

  2) -numa node,nodeid=0,cpus=0,mem=20480

Later, when QEMU boots up and cpuset CGroup controller is
available we further restrict QEMU there too. But there's a
behaviour difference hidden: while in case 1) QEMU is restricted
from beginning, in case 2) it is not and thus it may happen that
it will allocate memory from different NUMA node and even though
CGroup will try to migrate it, it may fail to do so (e.g. because
memory is locked). Therefore, one can argue that case 2) is
broken. NB, case 2) is exactly what mode 'restrictive' is for.
However, in case 1) we are unable to update QEMU with new
host-nodes, simply because it's lacking a command to do so.

For guests without NUMA:
It's very close to case 2) from above. We have commit
v7.10.0-rc1~163 that prevents us from outputting host-nodes when
generating memory-backend-* for system memory, but that simply
allows QEMU to allocate memory anywhere and then relies on
CGroups to move it to desired location.

Due to all of this, there is no reliable way to change nodeset
for mode 'strict'. Let's forbid it.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
docs/manpages/virsh.rst
src/libvirt-domain.c
src/qemu/qemu_driver.c

index baee508d04fd340c8c911d13a6bb61605cb28022..9decdee9256acb7efbc0a7609851afa3ff783055 100644 (file)
@@ -3549,7 +3549,7 @@ displayed.
 \'restrictive' or any valid number from the virDomainNumatuneMemMode enum
 in case the daemon supports it.  For a running domain, the mode can't be
 changed, and the nodeset can be changed only if the domain was started with
-a mode of either \`strict' or \`restrictive'.
+\`restrictive' mode.
 
 *nodeset* is a list of numa nodes used by the host for running the domain.
 Its syntax is a comma separated list, with '-' for ranges and '^' for
index 90b8918bb5273b306985c85f299c97b3850fcaa3..c36874f91e136da36da1952545e04dae16eda861 100644 (file)
@@ -2185,8 +2185,7 @@ virDomainGetMemoryParameters(virDomainPtr domain,
  * Changing live configuration may be possible only in some cases. For
  * instance, for QEMU driver the mode (VIR_DOMAIN_NUMA_MODE) can not be
  * changed, and changing the nodeset (VIR_DOMAIN_NUMA_NODESET) is possible
- * only for VIR_DOMAIN_NUMATUNE_MEM_STRICT and
- * VIR_DOMAIN_NUMATUNE_MEM_RESTRICTIVE modes.
+ * only for VIR_DOMAIN_NUMATUNE_MEM_RESTRICTIVE mode.
  *
  * Changing persistent configuration does not pose such limitations.
  *
index e884dde7217eda9db0540af38dacf029bda34ffd..0354e1474c76b91451f2148f8e78a4a906363a8d 100644 (file)
@@ -8777,10 +8777,9 @@ qemuDomainSetNumaParamsLive(virDomainObj *vm,
     size_t i = 0;
 
     if (virDomainNumatuneGetMode(vm->def->numa, -1, &mode) == 0 &&
-        mode != VIR_DOMAIN_NUMATUNE_MEM_STRICT &&
         mode != VIR_DOMAIN_NUMATUNE_MEM_RESTRICTIVE) {
         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("change of nodeset for running domain requires strict or restrictive numa mode"));
+                       _("change of nodeset for running domain requires restrictive numa mode"));
         return -1;
     }
 
@@ -8913,17 +8912,31 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
             goto endjob;
         }
 
-        if (nodeset &&
-            qemuDomainSetNumaParamsLive(vm, nodeset) < 0)
-            goto endjob;
+        if (mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
+            virBitmap *config_nodeset = NULL;
 
-        if (virDomainNumatuneSet(def->numa,
-                                 def->placement_mode ==
-                                 VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
-                                 -1, mode, nodeset) < 0)
-            goto endjob;
+            if (virDomainNumatuneMaybeGetNodeset(def->numa, priv->autoNodeset,
+                                                 &config_nodeset, -1) < 0)
+                goto endjob;
 
-        qemuDomainSaveStatus(vm);
+            if (!virBitmapEqual(nodeset, config_nodeset)) {
+                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                               _("can't change nodeset for strict mode for running domain"));
+                goto endjob;
+            }
+        } else {
+            if (nodeset &&
+                qemuDomainSetNumaParamsLive(vm, nodeset) < 0)
+                goto endjob;
+
+            if (virDomainNumatuneSet(def->numa,
+                                     def->placement_mode ==
+                                     VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
+                                     -1, mode, nodeset) < 0)
+                goto endjob;
+
+            qemuDomainSaveStatus(vm);
+        }
     }
 
     if (persistentDef) {