qemu: Fix qemuProcessInitCpuAffinity()

Ever since the feature was introduced with commit 0f8e7ae33a,
it has contained a logic error in that it attempted to use a NUMA
node map where a CPU map was expected.

Because of that, guests using <numatune> might fail to start:

  # virsh start guest
  error: Failed to start domain guest
  error: cannot set CPU affinity on process 40055: Invalid argument

This was particularly easy to trigger on POWER 8 machines, where
secondary threads always show up as offline in the host: having

  <numatune>
    <memory mode='strict' placement='static' nodeset='1'/>
  </numatune>

in the guest configuration, for example, would result in libvirt
trying to set the process affinity so that it would prefer
running on CPU 1, but since that's a secondary thread and thus
shows up as offline, the operation would fail, and so would
starting the guest.

Use the newly introduced virNumaNodesetToCPUset() to convert the
NUMA node map to a CPU map, which in the example above would be
48,56,64,72,80,88 - a valid input for virProcessSetAffinity().

https://bugzilla.redhat.com/show_bug.cgi?id=1703661

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Andrea Bolognani 2019-05-30 19:20:34 +02:00
parent 2d2b26f96f
commit 5f2212c062

View File

@ -2489,11 +2489,16 @@ qemuProcessInitCpuAffinity(virDomainObjPtr vm)
if (virDomainNumaGetNodeCount(vm->def->numa) <= 1 && if (virDomainNumaGetNodeCount(vm->def->numa) <= 1 &&
virDomainNumatuneGetMode(vm->def->numa, -1, &mem_mode) == 0 && virDomainNumatuneGetMode(vm->def->numa, -1, &mem_mode) == 0 &&
mem_mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) { mem_mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
virBitmapPtr nodeset = NULL;
if (virDomainNumatuneMaybeGetNodeset(vm->def->numa, if (virDomainNumatuneMaybeGetNodeset(vm->def->numa,
priv->autoNodeset, priv->autoNodeset,
&cpumapToSet, &nodeset,
-1) < 0) -1) < 0)
goto cleanup; goto cleanup;
if (virNumaNodesetToCPUset(nodeset, &cpumapToSet) < 0)
goto cleanup;
} else if (vm->def->cputune.emulatorpin) { } else if (vm->def->cputune.emulatorpin) {
cpumapToSet = vm->def->cputune.emulatorpin; cpumapToSet = vm->def->cputune.emulatorpin;
} else { } else {