[PATCH v3 4/8] qemu_domain: Introduce qemuDomainSchedCoreStart()
Daniel P. Berrangé
berrange at redhat.com
Tue Aug 23 16:03:07 UTC 2022
On Fri, Aug 12, 2022 at 12:04:19PM +0200, Michal Privoznik wrote:
> 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 <mprivozn at redhat.com>
> ---
> 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 9d5dd07958..6b30aec67d 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -1747,6 +1747,8 @@ qemuDomainObjPrivateFree(void *data)
> g_object_unref(priv->eventThread);
> }
>
> + qemuDomainSchedCoreStop(priv);
> +
> g_free(priv);
> }
>
> @@ -1778,6 +1780,9 @@ qemuDomainObjPrivateAlloc(void *opaque)
> priv->migMaxBandwidth = QEMU_DOMAIN_MIG_BANDWIDTH_MAX;
> priv->driver = opaque;
>
> + priv->schedCoreChildPID = -1;
> + priv->schedCoreChildFD = -1;
> +
> return g_steal_pointer(&priv);
> }
>
> @@ -11691,3 +11696,103 @@ qemuDomainObjWait(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"));
> + goto error;
> + }
> +
> + ignore_value(saferead(waitfd[0], &c, 1));
> +
> + VIR_FORCE_CLOSE(waitfd[0]);
Surely we need _exit(0) - otherwise this code falls through and
runs waaaaay to much other stuff in the child process.
THe above "goto error" needs to be an exit too.
> + } 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 592ee9805b..620830ccf5 100644
> --- a/src/qemu/qemu_domain.h
> +++ b/src/qemu/qemu_domain.h
> @@ -244,6 +244,11 @@ struct _qemuDomainObjPrivate {
>
> unsigned long long originalMemlock; /* Original RLIMIT_MEMLOCK, zero if no
> * restore will be required later */
> +
> + /* 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) \
> @@ -1098,3 +1103,10 @@ qemuDomainRemoveLogs(virQEMUDriver *driver,
>
> int
> qemuDomainObjWait(virDomainObj *vm);
> +
> +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 cfcf879f59..8b027f2d39 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -7502,6 +7502,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;
>
> @@ -7774,6 +7777,7 @@ qemuProcessLaunch(virConnectPtr conn,
> ret = 0;
>
> cleanup:
> + qemuDomainSchedCoreStop(priv);
> qemuDomainSecretDestroy(vm);
> return ret;
> }
> --
> 2.35.1
>
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
More information about the libvir-list
mailing list