From: Denis V. Lunev <[email protected]>

cpr-exec kills a VM whose memory backend has host-nodes when the cgroup
no longer allows those nodes. The old QEMU saves its state, the new one
exits during startup with

  cannot bind memory to host NUMA nodes: Invalid argument

and the guest is lost.

Guest RAM survives CPR: its fd is passed to the new QEMU or its backing
file is reopened, and the pages stay where they are. For shmem-backed
memory the policy set by mbind() lives in the shared object and survives
as well. host_memory_backend_memory_complete() treats the memory as
fresh anyway: it calls mbind() with MPOL_MF_STRICT | MPOL_MF_MOVE and
preallocates again. cpr-exec keeps the PID and the cgroup, so if
cpuset.mems has been changed to nodes outside host-nodes since the VM
started, mbind() returns EINVAL and QEMU exits. Where it succeeds, it
only walks or migrates pages that are already in place, while the guest
is stopped.

Skip the NUMA binding and preallocation on incoming CPR. The source
blocks CPR while any RAM block cannot be preserved, so every backend
created in this mode is an inherited one. This covers cpr-transfer too,
where the new process may be placed in a cgroup that does not allow the
original nodes. For a file backend outside shmem the VMA policy is not
restored, which affects only pages first touched after the update.
Memory added after the incoming migration completes is back on the
normal path.

Fixes: 2b7e9739fad8 ("physmem: preserve ram blocks for cpr")
Suggested-by: Andrey Drobyshev <[email protected]>
Signed-off-by: Denis V. Lunev <[email protected]>
Cc: David Hildenbrand <[email protected]>
Cc: Igor Mammedov <[email protected]>
Cc: "Maciej S. Szmigiero" <[email protected]>
Cc: Peter Xu <[email protected]>
Cc: Fabiano Rosas <[email protected]>
Cc: Mark Kanda <[email protected]>
Cc: Ben Chaney <[email protected]>
Cc: Steve Sistare <[email protected]>
Cc: [email protected]
---
 backends/hostmem.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/backends/hostmem.c b/backends/hostmem.c
index 02846b597d..26c7fce1cb 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -24,6 +24,7 @@
 #include "qemu/madvise.h"
 #include "qemu/cutils.h"
 #include "hw/core/qdev.h"
+#include "migration/cpr.h"
 
 #ifdef CONFIG_NUMA
 #include <numaif.h>
@@ -365,6 +366,10 @@ host_memory_backend_memory_complete(UserCreatable *uc, 
Error **errp)
     if (!backend->dump) {
         qemu_madvise(ptr, sz, QEMU_MADV_DONTDUMP);
     }
+    /* Memory inherited over CPR already has its pages and policy */
+    if (cpr_is_incoming()) {
+        return;
+    }
 #ifdef CONFIG_NUMA
     unsigned long lastbit = find_last_bit(backend->host_nodes, MAX_NODES);
     /* lastbit == MAX_NODES means maxnode = 0 */
-- 
2.53.0


Reply via email to