[PATCH 2/2] qemu: Do not Use canonical path for system memory

Igor Mammedov imammedo at redhat.com
Tue Jan 12 19:21:19 UTC 2021


On Tue, 12 Jan 2021 09:29:50 +0100
Michal Privoznik <mprivozn at redhat.com> wrote:

> In commit v6.9.0-rc1~450 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 v5.0.0-rc0~75^2~1^2~76 and
> look at function create_default_memdev().
> 
> However, then commit v5.0.0-rc1~11^2~3 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 XXX. 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.
> 
> Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1912201
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
> 
> I'll replace both occurrences of 'QEMU commit XXX' once QEMU patch is
> merged.
> 
>  src/qemu/qemu_command.c                       | 30 ++++++++++++++++---
>  src/qemu/qemu_command.h                       |  3 +-
>  src/qemu/qemu_hotplug.c                       |  2 +-
>  .../hugepages-memaccess3.x86_64-latest.args   |  4 +--
>  4 files changed, 31 insertions(+), 8 deletions(-)
> 
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 6f970a3128..b99d4e5faf 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -2950,7 +2950,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;
> @@ -2967,6 +2968,7 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
>      bool needHugepage = !!pagesize;
>      bool useHugepage = !!pagesize;
>      int discard = mem->discard;
> +    bool useCanonicalPath = true;
>  
>      /* The difference between @needHugepage and @useHugepage is that the latter
>       * is true whenever huge page is defined for the current memory cell.
> @@ -3081,6 +3083,9 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
>          if (qemuBuildMemoryBackendPropsShare(props, memAccess) < 0)
>              return -1;
>  
> +        if (systemMemory)
> +            useCanonicalPath = false;
> +
>      } else if (useHugepage || mem->nvdimmPath || memAccess ||
>          def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) {
>  
> @@ -3122,10 +3127,27 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
>  
>          if (qemuBuildMemoryBackendPropsShare(props, memAccess) < 0)
>              return -1;
> +
> +        if (systemMemory)
> +            useCanonicalPath = false;
> +
>      } 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'.
> +     * See QEMU commit XXX.
> +     */
> +    if (!useCanonicalPath &&
> +        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;

is it possible to do it only for old machine types <= 4.0, to limit hack exposure?


>      if (!priv->memPrealloc &&
>          virJSONValueObjectAdd(props, "B:prealloc", prealloc, NULL) < 0)
>          return -1;
> @@ -3237,7 +3259,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)
> @@ -3266,7 +3288,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)
> @@ -7065,7 +7087,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)
> diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
> index 3cfe6ff3e9..32cb013172 100644
> --- a/src/qemu/qemu_command.h
> +++ b/src/qemu/qemu_command.h
> @@ -153,7 +153,8 @@ int qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
>                                  qemuDomainObjPrivatePtr priv,
>                                  const virDomainDef *def,
>                                  const virDomainMemoryDef *mem,
> -                                bool force);
> +                                bool force,
> +                                bool systemMemory);
>  
>  char *
>  qemuBuildMemoryDeviceStr(const virDomainDef *def,
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index f336a90c8e..18d8cc06f5 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -2426,7 +2426,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)
> diff --git a/tests/qemuxml2argvdata/hugepages-memaccess3.x86_64-latest.args b/tests/qemuxml2argvdata/hugepages-memaccess3.x86_64-latest.args
> index 6033950eab..9396441b92 100644
> --- a/tests/qemuxml2argvdata/hugepages-memaccess3.x86_64-latest.args
> +++ b/tests/qemuxml2argvdata/hugepages-memaccess3.x86_64-latest.args
> @@ -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 \




More information about the libvir-list mailing list