]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Do not Use canonical path for system memory
authorMichal Privoznik <mprivozn@redhat.com>
Fri, 8 Jan 2021 15:35:26 +0000 (16:35 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 11 Feb 2021 07:43:14 +0000 (08:43 +0100)
In commit 88957116c9d3cb4705380c3702c9d4315fb500bb I've adapted
libvirt to QEMU's deprecation of -mem-path and -mem-prealloc and
switched to memory-backend-* even for system memory. My claim was
that that's what QEMU does under the hood anyway. And indeed it
was: see QEMU commit 900c0ba373aada4c13d47d95330aa72ec4067ba5 and
look at function create_default_memdev().

However, then commit d96c4d5f193e0e45beec80a6277728b32875bddb was
merged into QEMU. While it was fixing a bug, it also changed the
create_default_memdev() function in which it started turning off
use of canonical path (by setting
"x-use-canonical-path-for-ramblock-id" attribute to false). This
wasn't documented until QEMU commit
8db0b20415c129cf5e577a593a4a0372d90b7cc9. The path affects
migration - the same path has to be used on the source and on the
destination. Therefore, if there is old guest started with '-m X'
it has "pc.ram" block which doesn't use canonical path and thus
when migrating to newer QEMU which uses memory-backend-* we have
to turn off the canonical path explicitly. Otherwise,
"/objects/pc.ram" path would be expected by QEMU which doesn't
match the source.

Ideally, we would need to set it only for some machine types
(4.0 and older) because newer machine types already do what we
are doing. However, we treat machine types as opaque strings and
therefore we don't want to parse nor inspect their versions. But
then again, newer machine types already do what we are doing in
this commit, so when old machine types are deprecated and removed
we can remove our hack and forget it ever happened.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1912201
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
src/qemu/qemu_command.c
src/qemu/qemu_command.h
src/qemu/qemu_hotplug.c
tests/qemuxml2argvdata/disk-vhostuser.x86_64-latest.args
tests/qemuxml2argvdata/hugepages-memaccess3.x86_64-latest.args

index f0333d4f1a57035db2ff3dafe973ce84d657df5e..6b6e0bfc343ff85142280151a3b3d805374ed910 100644 (file)
@@ -2975,7 +2975,8 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
                             qemuDomainObjPrivatePtr priv,
                             const virDomainDef *def,
                             const virDomainMemoryDef *mem,
-                            bool force)
+                            bool force,
+                            bool systemMemory)
 {
     const char *backendType = "memory-backend-file";
     virDomainNumatuneMemMode mode;
@@ -2992,6 +2993,10 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
     bool needHugepage = !!pagesize;
     bool useHugepage = !!pagesize;
     int discard = mem->discard;
+    bool disableCanonicalPath = false;
+
+    /* Disabling canonical path is required for migration compatibility of
+     * system memory objects, see below */
 
     /* The difference between @needHugepage and @useHugepage is that the latter
      * is true whenever huge page is defined for the current memory cell.
@@ -3106,6 +3111,9 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
         if (qemuBuildMemoryBackendPropsShare(props, memAccess) < 0)
             return -1;
 
+        if (systemMemory)
+            disableCanonicalPath = true;
+
     } else if (useHugepage || mem->nvdimmPath || memAccess ||
         def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) {
 
@@ -3148,10 +3156,29 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
 
         if (qemuBuildMemoryBackendPropsShare(props, memAccess) < 0)
             return -1;
+
+        if (systemMemory)
+            disableCanonicalPath = true;
+
     } else {
         backendType = "memory-backend-ram";
     }
 
+    /* This is a terrible hack, but unfortunately there is no better way.
+     * The replacement for '-m X' argument is not simple '-machine
+     * memory-backend' and '-object memory-backend-*,size=X' (which was the
+     * idea). This is because of create_default_memdev() in QEMU sets
+     * 'x-use-canonical-path-for-ramblock-id' attribute to false and is
+     * documented in QEMU in qemu-options.hx under 'memory-backend'. Note
+     * that QEMU consideres 'x-use-canonical-path-for-ramblock-id' stable
+     * and supported despite the 'x-' prefix.
+     * See QEMU commit 8db0b20415c129cf5e577a593a4a0372d90b7cc9.
+     */
+    if (disableCanonicalPath &&
+        virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_X_USE_CANONICAL_PATH_FOR_RAMBLOCK_ID) &&
+        virJSONValueObjectAdd(props, "b:x-use-canonical-path-for-ramblock-id", false, NULL) < 0)
+        return -1;
+
     if (!priv->memPrealloc &&
         virJSONValueObjectAdd(props, "B:prealloc", prealloc, NULL) < 0)
         return -1;
@@ -3263,7 +3290,7 @@ qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
     mem.info.alias = alias;
 
     if ((rc = qemuBuildMemoryBackendProps(&props, alias, cfg,
-                                          priv, def, &mem, false)) < 0)
+                                          priv, def, &mem, false, false)) < 0)
         return -1;
 
     if (virQEMUBuildObjectCommandlineFromJSON(buf, props) < 0)
@@ -3292,7 +3319,7 @@ qemuBuildMemoryDimmBackendStr(virBufferPtr buf,
     alias = g_strdup_printf("mem%s", mem->info.alias);
 
     if (qemuBuildMemoryBackendProps(&props, alias, cfg,
-                                    priv, def, mem, true) < 0)
+                                    priv, def, mem, true, false) < 0)
         return -1;
 
     if (virQEMUBuildObjectCommandlineFromJSON(buf, props) < 0)
@@ -7105,7 +7132,7 @@ qemuBuildMemCommandLineMemoryDefaultBackend(virCommandPtr cmd,
     mem.info.alias = (char *) defaultRAMid;
 
     if (qemuBuildMemoryBackendProps(&props, defaultRAMid, cfg,
-                                    priv, def, &mem, false) < 0)
+                                    priv, def, &mem, false, true) < 0)
         return -1;
 
     if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0)
index a33fbf6f4e0e95616bcf2a7bb3d82578d02fcb30..bdae117e02efd3327a969f51f80ae9051715b5d9 100644 (file)
@@ -161,7 +161,8 @@ int qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
                                 qemuDomainObjPrivatePtr priv,
                                 const virDomainDef *def,
                                 const virDomainMemoryDef *mem,
-                                bool force);
+                                bool force,
+                                bool systemMemory);
 
 char *
 qemuBuildMemoryDeviceStr(const virDomainDef *def,
index dc2b46057c8de47dbdb9bb88c287f767f5a061ac..e7863328db2b51e0d2d1a0ff3fdcd885f36b3b36 100644 (file)
@@ -2430,7 +2430,7 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
         goto cleanup;
 
     if (qemuBuildMemoryBackendProps(&props, objalias, cfg,
-                                    priv, vm->def, mem, true) < 0)
+                                    priv, vm->def, mem, true, false) < 0)
         goto cleanup;
 
     if (qemuProcessBuildDestroyMemoryPaths(driver, vm, mem, true) < 0)
index 30acd7c78bfe153e476cec2d105ebc9aa7b68f1c..9ee855d5c79323274551d6221a2dc362f84f715e 100644 (file)
@@ -15,7 +15,8 @@ file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
 -machine pc,accel=tcg,usb=off,dump-guest-core=off,memory-backend=pc.ram \
 -cpu qemu64 \
 -m 214 \
--object memory-backend-memfd,id=pc.ram,share=yes,size=224395264 \
+-object memory-backend-memfd,id=pc.ram,share=yes,\
+x-use-canonical-path-for-ramblock-id=no,size=224395264 \
 -overcommit mem-lock=off \
 -smp 1,sockets=1,cores=1,threads=1 \
 -uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
index 6033950eabaa2b3fa58874917b2668208e50684e..9396441b925796f42a629b384bdfaad31781695c 100644 (file)
@@ -19,8 +19,8 @@ arch-capabilities=on,ssbd=on,xsaves=on,cmp-legacy=on,amd-ssbd=on,virt-ssbd=on,\
 rdctl-no=on,skip-l1dfl-vmentry=on,mds-no=on,pschange-mc-no=on \
 -m 4096 \
 -object memory-backend-file,id=pc.ram,\
-mem-path=/dev/hugepages2M/libvirt/qemu/-1-fedora,share=yes,prealloc=yes,\
-size=4294967296 \
+mem-path=/dev/hugepages2M/libvirt/qemu/-1-fedora,share=yes,\
+x-use-canonical-path-for-ramblock-id=no,prealloc=yes,size=4294967296 \
 -overcommit mem-lock=off \
 -smp 4,sockets=4,cores=1,threads=1 \
 -uuid 63840878-0deb-4095-97e6-fc444d9bc9fa \