]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu_domain: Introduce qemuDomainSchedCoreStart()
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 10 Aug 2022 15:17:42 +0000 (17:17 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 20 Oct 2022 06:58:18 +0000 (08:58 +0200)
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@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_process.c

index 7cc58d9e2e25bb8b2129cc8553c8789aa4290018..9ef6c8bb644d6cdc653404fc1b5369f4b7c2ca19 100644 (file)
@@ -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;
+    }
+}
index d2e5d4661a21b0d07353cee6acd3b2ac32377aeb..2bbd492d62da35c21399d7295666c1b31c97017a 100644 (file)
@@ -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);
index fe98601fcebdb936bd202f97a9e819e29c82e769..691bbd0edd8eac68bbbc12349f32f489beb9bdec 100644 (file)
@@ -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;
 }