From 4be75216bedd7621e2266044776a50c0a6a6505b Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Wed, 10 Aug 2022 17:17:42 +0200 Subject: [PATCH] qemu_domain: Introduce qemuDomainSchedCoreStart() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The aim of this helper function is to spawn a child process in which new scheduling group is created. This dummy process will then used to distribute scheduling group from (e.g. when starting helper processes or QEMU itself). The process is not needed for QEMU_SCHED_CORE_NONE case (obviously) nor for QEMU_SCHED_CORE_VCPUS case (because in that case a slightly different child will be forked off). Signed-off-by: Michal Privoznik Reviewed-by: Daniel P. Berrangé --- src/qemu/qemu_domain.c | 105 ++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_domain.h | 12 +++++ src/qemu/qemu_process.c | 4 ++ 3 files changed, 121 insertions(+) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 7cc58d9e2e..9ef6c8bb64 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1783,6 +1783,8 @@ qemuDomainObjPrivateFree(void *data) if (priv->statsSchema) g_clear_pointer(&priv->statsSchema, g_hash_table_destroy); + qemuDomainSchedCoreStop(priv); + g_free(priv); } @@ -1806,6 +1808,9 @@ qemuDomainObjPrivateAlloc(void *opaque) priv->statsSchema = NULL; + priv->schedCoreChildPID = -1; + priv->schedCoreChildFD = -1; + return g_steal_pointer(&priv); } @@ -12070,3 +12075,103 @@ qemuDomainSyncRxFilter(virDomainObj *vm, return 0; } + + +int +qemuDomainSchedCoreStart(virQEMUDriverConfig *cfg, + virDomainObj *vm) +{ + qemuDomainObjPrivate *priv = vm->privateData; + int waitfd[2] = { -1, -1 }; + int syncfd[2] = { -1, -1 }; + pid_t child = -1; + + if (cfg->schedCore == QEMU_SCHED_CORE_NONE || + cfg->schedCore == QEMU_SCHED_CORE_VCPUS) { + /* We don't need any dummy process for any of these two variants. */ + return 0; + } + + if (virPipe(waitfd) < 0 || + virPipe(syncfd) < 0) + return -1; + + if ((child = virFork()) < 0) + goto error; + + if (child == 0) { + /* child */ + int rc; + char c; + + VIR_FORCE_CLOSE(waitfd[1]); + VIR_FORCE_CLOSE(syncfd[0]); + + errno = 0; + rc = virProcessSchedCoreCreate(); + c = errno; + ignore_value(safewrite(syncfd[1], &c, 1)); + VIR_FORCE_CLOSE(syncfd[1]); + + if (rc < 0) { + virReportSystemError(errno, "%s", + _("Unable to set SCHED_CORE")); + _exit(EXIT_FAILURE); + } + + ignore_value(saferead(waitfd[0], &c, 1)); + VIR_FORCE_CLOSE(waitfd[0]); + _exit(EXIT_SUCCESS); + } else { + /* parent */ + char c = '\0'; + VIR_FORCE_CLOSE(waitfd[0]); + VIR_FORCE_CLOSE(syncfd[1]); + + if (saferead(syncfd[0], &c, 1) < 0) { + virReportSystemError(errno, "%s", + _("unable to read from pipe")); + goto error; + } + VIR_FORCE_CLOSE(syncfd[0]); + + if (c != 0) { + virReportSystemError(c, "%s", + _("Unable to set SCHED_CORE")); + goto error; + } + + VIR_DEBUG("Spawned dummy process for schedCore (%s) pid=%lld fd=%d", + virQEMUSchedCoreTypeToString(cfg->schedCore), + (long long) child, waitfd[1]); + + priv->schedCoreChildPID = child; + priv->schedCoreChildFD = waitfd[1]; + } + + return 0; + + error: + VIR_FORCE_CLOSE(waitfd[0]); + VIR_FORCE_CLOSE(waitfd[1]); + VIR_FORCE_CLOSE(syncfd[0]); + VIR_FORCE_CLOSE(syncfd[1]); + return -1; +} + + +void +qemuDomainSchedCoreStop(qemuDomainObjPrivate *priv) +{ + if (priv->schedCoreChildFD != -1) { + ignore_value(safewrite(priv->schedCoreChildFD, "q", 1)); + VIR_FORCE_CLOSE(priv->schedCoreChildFD); + } + + if (priv->schedCoreChildPID != -1) { + VIR_DEBUG("Killing dummy procces for schedCore pid=%lld", + (long long) priv->schedCoreChildPID); + virProcessAbort(priv->schedCoreChildPID); + priv->schedCoreChildPID = -1; + } +} diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index d2e5d4661a..2bbd492d62 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -244,6 +244,11 @@ struct _qemuDomainObjPrivate { * restore will be required later */ GHashTable *statsSchema; /* (name, data) pair for stats */ + + /* Info on dummy process for schedCore. A short lived process used only + * briefly when starting a guest. Don't save/parse into XML. */ + pid_t schedCoreChildPID; + pid_t schedCoreChildFD; }; #define QEMU_DOMAIN_PRIVATE(vm) \ @@ -1108,3 +1113,10 @@ int qemuDomainSyncRxFilter(virDomainObj *vm, virDomainNetDef *def, virDomainAsyncJob asyncJob); + +int +qemuDomainSchedCoreStart(virQEMUDriverConfig *cfg, + virDomainObj *vm); + +void +qemuDomainSchedCoreStop(qemuDomainObjPrivate *priv); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index fe98601fce..691bbd0edd 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -7479,6 +7479,9 @@ qemuProcessLaunch(virConnectPtr conn, if (qemuProcessGenID(vm, flags) < 0) goto cleanup; + if (qemuDomainSchedCoreStart(cfg, vm) < 0) + goto cleanup; + if (qemuExtDevicesStart(driver, vm, incoming != NULL) < 0) goto cleanup; @@ -7751,6 +7754,7 @@ qemuProcessLaunch(virConnectPtr conn, ret = 0; cleanup: + qemuDomainSchedCoreStop(priv); qemuDomainSecretDestroy(vm); return ret; } -- 2.39.5