Re: [PATCH v2 1/4] qemu.conf changes to support multiple memory backend

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Jun 05, 2024 at 04:37:35PM -0400, mgalaxy@xxxxxxxxxx wrote:
From: Michael Galaxy <mgalaxy@xxxxxxxxxx>


Hi,

sorry for such a late reply and thank you for the patches.  There are
few things that need tweaking and the series does not apply cleanly,
but fortunately there is only one conflict.  Once needed adjustments are
incorporated I see no reason why this should not be supported.  What I
found is provided inline.

We start by introducing a backwards-compatible, comma-separated
specification that will not break existing installations, such
as in the following example:

$ cat qemu.conf | grep memory_backing_dir
memory_backing_dir = ["/path/to/pmem/0", "/path/to/pmem/1"]

(The old syntax with a single string is also still supported)
memory_backing_dir = "/path/to/dir"

In our case, we almost always have two NUMA nodes, so in that
example, we have two PMEM regions which are created on the
Linux kernel command line that get mounted into those two
locations for libvirt to use.

Signed-off-by: Michael Galaxy <mgalaxy@xxxxxxxxxx>
---
src/qemu/qemu_command.c |   8 ++-
src/qemu/qemu_conf.c    | 141 +++++++++++++++++++++++++++++++++++-----
src/qemu/qemu_conf.h    |  14 ++--
src/qemu/qemu_driver.c  |  29 +++++----
src/qemu/qemu_hotplug.c |   6 +-
src/qemu/qemu_process.c |  44 +++++++------
src/qemu/qemu_process.h |   7 +-
7 files changed, 188 insertions(+), 61 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2d0eddc79e..9a25fdb0ed 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3420,7 +3420,9 @@ qemuBuildMemoryBackendProps(virJSONValue **backendProps,
        } else {
            /* We can have both pagesize and mem source. If that's the case,
             * prefer hugepages as those are more specific. */
-            if (qemuGetMemoryBackingPath(priv->driver, def, mem->info.alias, &memPath) < 0)
+
+            virDomainXMLPrivateDataCallbacks *privateData = (virDomainXMLPrivateDataCallbacks *) priv;

I guess this is some leftover from previous versions.  The pointer is
not to virDomainXMLPrivateDataCallbacks and should not be cast to it.
Especially when you cast it back in the function you pass it to.

+            if (qemuGetMemoryBackingPath(def, privateData, mem->targetNode, mem->info.alias, &memPath) < 0)
                return -1;
        }

@@ -7295,7 +7297,9 @@ qemuBuildMemPathStr(const virDomainDef *def,
            return -1;
        prealloc = true;
    } else if (def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) {
-        if (qemuGetMemoryBackingPath(priv->driver, def, "ram", &mem_path) < 0)
+        // This path should not be reached if NUMA is requested
+        virDomainXMLPrivateDataCallbacks *privateData = (virDomainXMLPrivateDataCallbacks *) priv;

Same here.

+        if (qemuGetMemoryBackingPath(def, privateData, 0, "ram", &mem_path) < 0)
            return -1;
    }

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 4050a82341..b808e33b77 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -43,6 +43,7 @@
#include "virfile.h"
#include "virstring.h"
#include "virutil.h"
+#include "virnuma.h"
#include "configmake.h"
#include "security/security_util.h"

@@ -137,6 +138,9 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,

    cfg->cgroupControllers = -1; /* -1 == auto-detect */

+    cfg->memoryBackingDirs = g_new0(char *, 1);
+    cfg->nb_memoryBackingDirs = 1;
+
    if (root != NULL) {
        cfg->logDir = g_strdup_printf("%s/log/qemu", root);
        cfg->swtpmLogDir = g_strdup_printf("%s/log/swtpm", root);
@@ -153,7 +157,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
        cfg->checkpointDir = g_strdup_printf("%s/checkpoint", cfg->libDir);
        cfg->autoDumpPath = g_strdup_printf("%s/dump", cfg->libDir);
        cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir);
-        cfg->memoryBackingDir = g_strdup_printf("%s/ram", cfg->libDir);
+        cfg->memoryBackingDirs[0] = g_strdup_printf("%s/ram", cfg->libDir);
    } else if (privileged) {
        cfg->logDir = g_strdup_printf("%s/log/libvirt/qemu", LOCALSTATEDIR);

@@ -174,7 +178,8 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
        cfg->checkpointDir = g_strdup_printf("%s/checkpoint", cfg->libDir);
        cfg->autoDumpPath = g_strdup_printf("%s/dump", cfg->libDir);
        cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir);
-        cfg->memoryBackingDir = g_strdup_printf("%s/ram", cfg->libDir);
+
+        cfg->memoryBackingDirs[0] = g_strdup_printf("%s/ram", cfg->libDir);
        cfg->swtpmStorageDir = g_strdup_printf("%s/lib/libvirt/swtpm",
                                               LOCALSTATEDIR);
    } else {
@@ -201,7 +206,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
                                             cfg->configBaseDir);
        cfg->autoDumpPath = g_strdup_printf("%s/qemu/dump", cfg->configBaseDir);
        cfg->nvramDir = g_strdup_printf("%s/qemu/nvram", cfg->configBaseDir);
-        cfg->memoryBackingDir = g_strdup_printf("%s/qemu/ram", cfg->configBaseDir);
+        cfg->memoryBackingDirs[0] = g_strdup_printf("%s/qemu/ram", cfg->configBaseDir);
        cfg->swtpmStorageDir = g_strdup_printf("%s/qemu/swtpm",
                                               cfg->configBaseDir);
    }
@@ -294,6 +299,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
static void virQEMUDriverConfigDispose(void *obj)
{
    virQEMUDriverConfig *cfg = obj;
+    size_t i;

    virBitmapFree(cfg->namespaces);

@@ -369,7 +375,12 @@ static void virQEMUDriverConfigDispose(void *obj)

    virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares);

-    g_free(cfg->memoryBackingDir);
+    for (i = 0; i < cfg->nb_memoryBackingDirs; i++) {
+        g_free(cfg->memoryBackingDirs[i]);
+    }
+
+    g_free(cfg->memoryBackingDirs);
+
    g_free(cfg->swtpmStorageDir);

    g_strfreev(cfg->capabilityfilters);
@@ -1018,15 +1029,22 @@ static int
virQEMUDriverConfigLoadMemoryEntry(virQEMUDriverConfig *cfg,
                                   virConf *conf)
{
-    g_autofree char *dir = NULL;
+    char **memoryBackingDirs = NULL;
+    g_auto(GStrv) params = NULL;

Unused variable.

    int rc;

-    if ((rc = virConfGetValueString(conf, "memory_backing_dir", &dir)) < 0)
+    if ((rc = virConfGetValueStringList(conf, "memory_backing_dir", true, &memoryBackingDirs) < 0))
        return -1;

-    if (rc > 0) {
-        VIR_FREE(cfg->memoryBackingDir);
-        cfg->memoryBackingDir = g_strdup_printf("%s/libvirt/qemu", dir);
+    if (rc == 0) {
+        size_t i;
+        for (i = 0; i < cfg->nb_memoryBackingDirs; i++)
+            g_free(cfg->memoryBackingDirs[i]);
+
+        cfg->nb_memoryBackingDirs = g_strv_length(memoryBackingDirs);
+        cfg->memoryBackingDirs = g_new0(char *, cfg->nb_memoryBackingDirs);
+        for (i = 0; i < cfg->nb_memoryBackingDirs; i++)
+            cfg->memoryBackingDirs[i] = g_strdup_printf("%s/libvirt/qemu", memoryBackingDirs[i]);
    }

    return 0;
@@ -1595,22 +1613,110 @@ qemuGetDomainHupageMemPath(virQEMUDriver *driver,


int
-qemuGetMemoryBackingDomainPath(virQEMUDriver *driver,
-                               const virDomainDef *def,
+qemuGetMemoryBackingDomainPath(const virDomainDef *def,
+                               virDomainXMLPrivateDataCallbacks *priv,

Change this to qemuDomainObjPrivate and ...

+                               const size_t targetNode,
                               char **path)
{
+    qemuDomainObjPrivate *privateData = (qemuDomainObjPrivate *) priv;

... remove this cast.

+    virQEMUDriver *driver = privateData->driver;
    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
    const char *root = driver->embeddedRoot;
    g_autofree char *shortName = NULL;
+    size_t path_index = 0; // original behavior, described below

    if (!(shortName = virDomainDefGetShortName(def)))
        return -1;

-    if (root && !STRPREFIX(cfg->memoryBackingDir, root)) {
+    /*
+     * We have three use cases:
+     *
+     * 1. Domain has multiple NUMA nodes, but they have only specified
+     *    a single directory path in qemu.conf. (Original default behavior).
+     *
+     *    In this case, we already placed the memory backing path for each NUMA node
+     *    into the same path location. Preserve the established default behavior.
+     *
+     * 2. Domain has multiple NUMA nodes, but we have asked for multiple directory
+     *    paths as well.
+     *
+     *    In this case, we will have a one-to-one relationship between the number
+     *    of NUMA nodes and the order in which the paths are provided.
+     *    If the user does not specify enough paths, then we need to throw an error.
+     *    NOTE: This is open to comment. The "ordering" of the paths here is not intially
+     *    configurable to preserve backwards compatibility with the original qemu.conf syntax.
+     *    If controlling the ordering is desired, we would need to revise the syntax in
+     *    qemu.conf to make that possible. That hasn't been needed so far.
+     *
+     *    NOTE A): We must check with numatune here, if requested. The number of NUMA nodes
+     *             may be less than or equal to the number of provided paths. If it is less,
+     *             we have to respect the choices made by numatune. In this case, we will map the
+     *             physical NUMA nodes (0, 1, 2...) in the order in which they appear in qemu.conf
+     *
+     * 3. Domain has a single NUMA node, but we have asked for multiple directory paths.
+     *
+     *       In this case we also need to check if numatune is requested. If so,
+     *       we want to pick the path indicated by numatune.
+     *
+     * NOTE B): In both cases 2 and 3, if numatune is requested, the path obviously cannot
+     *         be changed on the fly, like it normally would be in "restrictive" mode
+     *         during runtime. So, we will only do this is the mode requested is "strict".
+     *
+     * NOTE C): Furthermore, in both cases 2 and 3, if the number of directory paths provided
+     *          is more than one, and one of either: a) no numatune is provided at all or
+     *          b) numatune is in fact provided, but the mode is not strict,
+     *          then we must thrown error. This is because we cannot know which backing

"we must throw an error"

+     *          directory path to choose without the user's input.
+     *
+     * NOTE D): If one or more directory paths is requested in any of the cases 1, 2, or 3,
+     *          the numatune cannot specifiy more than one NUMA node, because the only mode
+     *          possible with directory paths is "strict" (e.g. automatic numa balancing of
+     *          memory will not work). Only one numa node can be requested by numatune, else
+     *          we must throw an error.
+     */
+
+    if (cfg->nb_memoryBackingDirs > 1) {
+        virDomainNuma *numatune = def->numa;

Just use def->numa, the temporary variable name is not used always below
and makes the code harder to read.

+        virBitmap *numaBitmap = virDomainNumatuneGetNodeset(numatune, privateData->autoNodeset, targetNode);
+        size_t numa_node_count = virDomainNumaGetNodeCount(def->numa);
+        virDomainNumatuneMemMode mode;
+
+        if ((numatune && numaBitmap && virNumaNodesetIsAvailable(numaBitmap)) &&

The parentheses are not needed here.

+            virDomainNumatuneGetMode(def->numa, -1, &mode) == 0 &&
+            mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT &&
+            virBitmapCountBits(numaBitmap) == 1) {
+
+            // Is numatune provided?
+            // Is it strict?
+            // Does it only specify a single pinning for this target?
+            // Yes to all 3? then good to go.
+
+            if (cfg->nb_memoryBackingDirs < numa_node_count) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,

I would not say this is an internal error, but maybe VIR_ERR_CONFIG_UNSUPPORTED.

+                               _("Domain requesting configuration for %1$lu NUMA nodes, but memory backing directory only has (%2$lu) directory paths available. Either reduce this to one directory or provide more paths to use."),
+                               numa_node_count,
+                               cfg->nb_memoryBackingDirs);
+                return -1;
+            }
+
+            path_index = virBitmapNextSetBit(numaBitmap, -1);

What if the single pinning is to the third host node, but there are only
two memoryBackingDirs supplied in the config?

+        } else if (numa_node_count > 1 && numa_node_count == cfg->nb_memoryBackingDirs) {
+            // Be nice. A valid numatune and pinning has not been specified, but the number
+            // of paths matches up exactly, so just assign them one-to-one.
+            path_index = targetNode;
+        } else {
+            virReportError(VIR_ERR_INTERNAL_ERROR,

Again, not an internal error.

+                           _("There are (%1$lu) memory directory directories configured. Domain must use a 'strict' numatune as well as an associated pinning configuration for each NUMA node before proceeding. An individual NUMA node can only be pinned to a single backing directory. Please correct the domain configuration or remove the memory backing directories and try again."),
+                cfg->nb_memoryBackingDirs);
+                return -1;
+        }
+    }
+
+    if (root && !STRPREFIX(cfg->memoryBackingDirs[path_index], root)) {
        g_autofree char * hash = virDomainDriverGenerateRootHash("qemu", root);
-        *path = g_strdup_printf("%s/%s-%s", cfg->memoryBackingDir, hash, shortName);
+        *path = g_strdup_printf("%s/%s-%s", cfg->memoryBackingDirs[path_index], hash, shortName);
    } else {
-        *path = g_strdup_printf("%s/%s", cfg->memoryBackingDir, shortName);
+        *path = g_strdup_printf("%s/%s", cfg->memoryBackingDirs[path_index], shortName);
    }

    return 0;
@@ -1630,8 +1736,9 @@ qemuGetMemoryBackingDomainPath(virQEMUDriver *driver,
 *          -1 otherwise (with error reported).
 */
int
-qemuGetMemoryBackingPath(virQEMUDriver *driver,
-                         const virDomainDef *def,
+qemuGetMemoryBackingPath(const virDomainDef *def,
+                         virDomainXMLPrivateDataCallbacks *priv,

Change this to qemuDomainObjPrivate *.

+                         const size_t targetNode,
                         const char *alias,
                         char **memPath)
{
@@ -1644,7 +1751,7 @@ qemuGetMemoryBackingPath(virQEMUDriver *driver,
        return -1;
    }

-    if (qemuGetMemoryBackingDomainPath(driver, def, &domainPath) < 0)
+    if (qemuGetMemoryBackingDomainPath(def, priv, targetNode, &domainPath) < 0)
        return -1;

    *memPath = g_strdup_printf("%s/%s", domainPath, alias);
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 36049b4bfa..dabf4d19a4 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -221,7 +221,8 @@ struct _virQEMUDriverConfig {
    unsigned int glusterDebugLevel;
    bool virtiofsdDebug;

-    char *memoryBackingDir;
+    char **memoryBackingDirs;
+    size_t nb_memoryBackingDirs;

We usually just prefix with "n" for the counters, even though it is not
always more readable, but to stay consistent please use "nmemoryBackingDirs".


    uid_t swtpm_user;
    gid_t swtpm_group;
@@ -369,11 +370,14 @@ int qemuGetDomainHupageMemPath(virQEMUDriver *driver,
                               unsigned long long pagesize,
                               char **memPath);

-int qemuGetMemoryBackingDomainPath(virQEMUDriver *driver,
-                                   const virDomainDef *def,
+int qemuGetMemoryBackingDomainPath(const virDomainDef *def,
+                                   virDomainXMLPrivateDataCallbacks *priv,
+                                   const size_t targetNode,
                                   char **path);
-int qemuGetMemoryBackingPath(virQEMUDriver *driver,
-                             const virDomainDef *def,
+
+int qemuGetMemoryBackingPath(const virDomainDef *def,
+                             virDomainXMLPrivateDataCallbacks *priv,
+                             const size_t targetNode,
                             const char *alias,
                             char **memPath);

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e2698c7924..51ca7dca78 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -653,11 +653,14 @@ qemuStateInitialize(bool privileged,
                             cfg->nvramDir);
        goto error;
    }
-    if (g_mkdir_with_parents(cfg->memoryBackingDir, 0777) < 0) {
-        virReportSystemError(errno, _("Failed to create memory backing dir %1$s"),
-                             cfg->memoryBackingDir);
-        goto error;
+    for (i = 0; i < cfg->nb_memoryBackingDirs; i++) {
+        if (g_mkdir_with_parents(cfg->memoryBackingDirs[i], 0777) < 0) {
+            virReportSystemError(errno, _("Failed to create memory backing dir # %1$lu @ %2$s, total: %3$lu"),
+            i, cfg->memoryBackingDirs[i], cfg->nb_memoryBackingDirs);

This line should be indented with the first parameter, if it gets too
long feel free to split each parameter to its own line.

+            goto error;
+        }
    }
+
    if (g_mkdir_with_parents(cfg->slirpStateDir, 0777) < 0) {
        virReportSystemError(errno, _("Failed to create slirp state dir %1$s"),
                             cfg->slirpStateDir);
@@ -802,12 +805,14 @@ qemuStateInitialize(bool privileged,
                                 (int)cfg->group);
            goto error;
        }
-        if (chown(cfg->memoryBackingDir, cfg->user, cfg->group) < 0) {
-            virReportSystemError(errno,
+        for (i = 0; i < cfg->nb_memoryBackingDirs; i++) {
+            if (chown(cfg->memoryBackingDirs[i], cfg->user, cfg->group) < 0) {
+                virReportSystemError(errno,
                                 _("unable to set ownership of '%1$s' to %2$d:%3$d"),
-                                 cfg->memoryBackingDir, (int)cfg->user,
+                                 cfg->memoryBackingDirs[i], (int)cfg->user,
                                 (int)cfg->group);

The indentation needs fixing here as well.

-            goto error;
+                goto error;
+            }
        }
        if (chown(cfg->slirpStateDir, cfg->user, cfg->group) < 0) {
            virReportSystemError(errno,
@@ -855,10 +860,12 @@ qemuStateInitialize(bool privileged,
            goto error;
    }

-    if (privileged &&
-        virFileUpdatePerm(cfg->memoryBackingDir,
+    for (i = 0; i < cfg->nb_memoryBackingDirs; i++) {
+        if (privileged &&
+            virFileUpdatePerm(cfg->memoryBackingDirs[i],
                          0, S_IXGRP | S_IXOTH) < 0)

Indentation.

-        goto error;
+            goto error;
+    }

    /* Get all the running persistent or transient configs first */
    if (virDomainObjListLoadAllConfigs(qemu_driver->domains,
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 4a3f4f657e..59db29aada 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -2276,7 +2276,7 @@ qemuDomainAttachMemory(virQEMUDriver *driver,
                                    priv, vm->def, mem, true, false, NULL) < 0)
        goto cleanup;

-    if (qemuProcessBuildDestroyMemoryPaths(driver, vm, mem, true) < 0)
+    if (qemuProcessBuildDestroyMemoryPaths(vm, mem, true) < 0)
        goto cleanup;

    if (qemuDomainNamespaceSetupMemory(vm, mem, &teardowndevice) < 0)
@@ -2351,7 +2351,7 @@ qemuDomainAttachMemory(virQEMUDriver *driver,
    qemuDomainObjExitMonitor(vm);

    if (objAdded && mem)
-        ignore_value(qemuProcessDestroyMemoryBackingPath(driver, vm, mem));
+        ignore_value(qemuProcessDestroyMemoryBackingPath(vm->def, priv, mem));

    virErrorRestore(&orig_err);
    if (!mem)
@@ -4634,7 +4634,7 @@ qemuDomainRemoveMemoryDevice(virQEMUDriver *driver,
    if (qemuDomainNamespaceTeardownMemory(vm, mem) <  0)
        VIR_WARN("Unable to remove memory device from /dev");

-    if (qemuProcessDestroyMemoryBackingPath(driver, vm, mem) < 0)
+    if (qemuProcessDestroyMemoryBackingPath(vm->def, priv, mem) < 0)
        VIR_WARN("Unable to destroy memory backing path");

    qemuDomainReleaseMemoryDeviceSlot(vm, mem);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 7ef7040a85..a9af8fe353 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4046,12 +4046,12 @@ qemuProcessBuildDestroyMemoryPathsImpl(virQEMUDriver *driver,


int
-qemuProcessBuildDestroyMemoryPaths(virQEMUDriver *driver,
-                                   virDomainObj *vm,
+qemuProcessBuildDestroyMemoryPaths(virDomainObj *vm,
                                   virDomainMemoryDef *mem,
                                   bool build)
{
-
+    qemuDomainObjPrivate *priv = vm->privateData;
+    virQEMUDriver *driver = priv->driver;

It's nice that you are removing the parameter `driver` which is not
needed since it can be extracted from another parameter `vm`, but this
really should be its own separate patch doing just that one thing.

The following patch, which changes functionality, will look much nicer
after that.  Not only for review, but also for the future if someone
needs to figure out what changed.

    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
    size_t i;
    bool shouldBuildHP = false;
@@ -4081,13 +4081,14 @@ qemuProcessBuildDestroyMemoryPaths(virQEMUDriver *driver,
    }

    if (!build || shouldBuildMB) {
-        g_autofree char *path = NULL;
-        if (qemuGetMemoryBackingDomainPath(driver, vm->def, &path) < 0)
-            return -1;
+        for (i = 0; i < cfg->nb_memoryBackingDirs; i++) {
+            g_autofree char *path = NULL;
+            if (qemuGetMemoryBackingDomainPath(vm->def, vm->privateData, i, &path) < 0)
+                return -1;

-        if (qemuProcessBuildDestroyMemoryPathsImpl(driver, vm,
-                                                   path, build) < 0)
-            return -1;
+            if (qemuProcessBuildDestroyMemoryPathsImpl(driver, vm, path, build) < 0)
+                return -1;
+        }
    }

    return 0;
@@ -4095,19 +4096,24 @@ qemuProcessBuildDestroyMemoryPaths(virQEMUDriver *driver,


int
-qemuProcessDestroyMemoryBackingPath(virQEMUDriver *driver,
-                                    virDomainObj *vm,
+qemuProcessDestroyMemoryBackingPath(virDomainDef *def,
+                                    qemuDomainObjPrivate *priv,
                                    virDomainMemoryDef *mem)

This function needs access to the driver, the domain definition and its
private data.  All those can be extracted from the domain object `vm`,
but more importantly all of them are accessible in all the callers
modified above.  Why make it more complicated and change the parameters
while changing the logic?  Either a) keep it the same or b) supply
everything so that this function is easier to read or c) supply the
minimum (just `vm`) so that this function is easier to call from various
places.  In this case probably not the last option (c) since it is
called from just two functions that have access to the same variables.

{
+    virQEMUDriver *driver = priv->driver;
    g_autofree char *path = NULL;
+    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+    size_t i;

-    if (qemuGetMemoryBackingPath(driver, vm->def, mem->info.alias, &path) < 0)
-        return -1;
+    for (i = 0; i < cfg->nb_memoryBackingDirs; i++) {
+        virDomainXMLPrivateDataCallbacks *privateData = (virDomainXMLPrivateDataCallbacks *) priv;
+        if (qemuGetMemoryBackingPath(def, privateData, i, mem->info.alias, &path) < 0)
+            return -1;


I wonder why are the paths not saved in the status XML of the running
domain.  Since they can be changed during the VM's lifetime (while
restarting libvirt) it could cause issues during clean-up.  Sure,
unlink() will set errno to ENOENT, but the proper paths will not be
cleaned up.  It'd also make this part of the code easier and safer to
use from the callers.  But that's pre-existing.

-    if (unlink(path) < 0 &&
-        errno != ENOENT) {
-        virReportSystemError(errno, _("Unable to remove %1$s"), path);
-        return -1;
+        if (unlink(path) < 0 && errno != ENOENT) {
+            virReportSystemError(errno, _("Unable to remove %1$s"), path);
+            return -1;
+        }
    }

    return 0;
@@ -7268,7 +7274,7 @@ qemuProcessPrepareHost(virQEMUDriver *driver,
    if (qemuProcessPrepareHostBackendChardev(vm) < 0)
        return -1;

-    if (qemuProcessBuildDestroyMemoryPaths(driver, vm, NULL, true) < 0)
+    if (qemuProcessBuildDestroyMemoryPaths(vm, NULL, true) < 0)
        return -1;

    /* Ensure no historical cgroup for this VM is lying around bogus
@@ -8482,7 +8488,7 @@ void qemuProcessStop(virQEMUDriver *driver,
        goto endjob;
    }

-    qemuProcessBuildDestroyMemoryPaths(driver, vm, NULL, false);
+    qemuProcessBuildDestroyMemoryPaths(vm, NULL, false);

    if (!!g_atomic_int_dec_and_test(&driver->nactive) && driver->inhibitCallback)
        driver->inhibitCallback(false, driver->inhibitOpaque);
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index c1ea949215..eebd0a4d1b 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -38,13 +38,12 @@ int qemuProcessStopCPUs(virQEMUDriver *driver,
                        virDomainPausedReason reason,
                        virDomainAsyncJob asyncJob);

-int qemuProcessBuildDestroyMemoryPaths(virQEMUDriver *driver,
-                                       virDomainObj *vm,
+int qemuProcessBuildDestroyMemoryPaths(virDomainObj *vm,
                                       virDomainMemoryDef *mem,
                                       bool build);

-int qemuProcessDestroyMemoryBackingPath(virQEMUDriver *driver,
-                                        virDomainObj *vm,
+int qemuProcessDestroyMemoryBackingPath(virDomainDef *def,
+                                        qemuDomainObjPrivate *priv,
                                        virDomainMemoryDef *mem);

void qemuProcessReconnectAll(virQEMUDriver *driver);
--
2.34.1


This patch changes the configuration, so it should also adjust the
documentation and since configuration is used everywhere it should also
add a few unit tests with the changed configuration and few edge cases,
just so we can be sure it really works the way it is supposed to.

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux