While technically thread-context objects can be reused, we only
use them (well, will use them) to pin memory allocation threads.
Therefore, once we connect to QEMU monitor, all memory (with
prealloc=yes) was allocated and thus these objects are no longer
needed and can be removed. For on demand allocation the TC object
is left behind.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/qemu/qemu_command.c | 7 ++++++
src/qemu/qemu_domain.c | 2 ++
src/qemu/qemu_domain.h | 2 ++
src/qemu/qemu_process.c | 47 +++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_process.h | 2 ++
5 files changed, 60 insertions(+)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 392b248628..90bc537b33 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3613,6 +3613,7 @@ qemuBuildThreadContextProps(virJSONValue **tcProps,
g_autoptr(virJSONValue) nodemaskCopy = NULL;
g_autofree char *tcAlias = NULL;
const char *memalias = NULL;
+ bool prealloc = false;
if (tcProps)
*tcProps = NULL;
@@ -3646,6 +3647,12 @@ qemuBuildThreadContextProps(virJSONValue **tcProps,
NULL) < 0)
return -1;
+ if (virJSONValueObjectGetBoolean(*memProps, "prealloc", &prealloc)
>= 0 &&
+ prealloc) {
+ priv->threadContextAliases = g_slist_prepend(priv->threadContextAliases,
+ g_steal_pointer(&tcAlias));
+ }
+
*tcProps = g_steal_pointer(&props);
return 0;
}
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 0d579bfc9b..ef1a9c8c74 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1811,6 +1811,8 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivate *priv)
priv->preMigrationMemlock = 0;
virHashRemoveAll(priv->statsSchema);
+
+ g_slist_free_full(g_steal_pointer(&priv->threadContextAliases), g_free);
}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index d5f4fbad12..a9af8502d2 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -251,6 +251,8 @@ struct _qemuDomainObjPrivate {
* briefly when starting a guest. Don't save/parse into XML. */
pid_t schedCoreChildPID;
pid_t schedCoreChildFD;
+
+ GSList *threadContextAliases; /* List of IDs of thread-context objects */
};
#define QEMU_DOMAIN_PRIVATE(vm) \
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 4b26c384cf..0769f30d74 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7500,6 +7500,50 @@ qemuProcessSetupLifecycleActions(virDomainObj *vm,
}
+int
+qemuProcessDeleteThreadContext(virDomainObj *vm)
+{
+ qemuDomainObjPrivate *priv = vm->privateData;
+ GSList *next = priv->threadContextAliases;
+ int ret = -1;
+
+ if (!next)
+ return 0;
+
+ for (; next; next = next->next) {
+ if (qemuMonitorDelObject(priv->mon, next->data, true) < 0)
+ goto cleanup;
+ }
+
+ ret = 0;
+ cleanup:
+ g_slist_free_full(g_steal_pointer(&priv->threadContextAliases), g_free);
+ return ret;
+}
+
+
+static int
+qemuProcessDeleteThreadContextHelper(virDomainObj *vm,
+ virDomainAsyncJob asyncJob)
+{
+ qemuDomainObjPrivate *priv = vm->privateData;
+ int ret = -1;
+
+ if (!priv->threadContextAliases)
+ return 0;
+
+ VIR_DEBUG("Deleting thread context objects");
+ if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
+ return -1;
+
+ ret = qemuProcessDeleteThreadContext(vm);
+
+ qemuDomainObjExitMonitor(vm);
+
+ return ret;
+}
+
+
/**
* qemuProcessLaunch:
*
@@ -7860,6 +7904,9 @@ qemuProcessLaunch(virConnectPtr conn,
if (qemuProcessSetupLifecycleActions(vm, asyncJob) < 0)
goto cleanup;
+ if (qemuProcessDeleteThreadContextHelper(vm, asyncJob) < 0)
+ goto cleanup;
+
ret = 0;
cleanup:
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index d1f58ee258..9a24745f15 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -123,6 +123,8 @@ int qemuProcessPrepareHost(virQEMUDriver *driver,
virDomainObj *vm,
unsigned int flags);
+int qemuProcessDeleteThreadContext(virDomainObj *vm);
+
int qemuProcessLaunch(virConnectPtr conn,
virQEMUDriver *driver,
virDomainObj *vm,
--
2.37.4