Signed-off-by: Vineeth Pillai <viremana(a)linux.microsoft.com>
Signed-off-by: Praveen K Paladugu <prapal(a)linux.microsoft.com>
---
src/ch/ch_driver.c | 278 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 278 insertions(+)
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 9ad23c1710..97dfda85e1 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -43,6 +43,7 @@
#include "viruri.h"
#include "virutil.h"
#include "viruuid.h"
+#include "virnuma.h"
#define VIR_FROM_THIS VIR_FROM_CH
@@ -1320,6 +1321,281 @@ chDomainPinVcpu(virDomainPtr dom,
VIR_DOMAIN_AFFECT_LIVE);
}
+#define CH_NB_NUMA_PARAM 2
+
+static int
+chDomainGetNumaParameters(virDomainPtr dom,
+ virTypedParameterPtr params,
+ int *nparams,
+ unsigned int flags)
+{
+ size_t i;
+ virDomainObj *vm = NULL;
+ virDomainNumatuneMemMode tmpmode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
+ virCHDomainObjPrivate *priv;
+ g_autofree char *nodeset = NULL;
+ int ret = -1;
+ virDomainDef *def = NULL;
+ bool live = false;
+ virBitmap *autoNodeset = NULL;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG |
+ VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+ if (!(vm = virCHDomainObjFromDomain(dom)))
+ return -1;
+ priv = vm->privateData;
+
+ if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0)
+ goto cleanup;
+
+ if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+ goto cleanup;
+
+ if (live)
+ autoNodeset = priv->autoNodeset;
+
+ if ((*nparams) == 0) {
+ *nparams = CH_NB_NUMA_PARAM;
+ ret = 0;
+ goto cleanup;
+ }
+
+ for (i = 0; i < CH_NB_NUMA_PARAM && i < *nparams; i++) {
+ virMemoryParameterPtr param = ¶ms[i];
+
+ switch (i) {
+ case 0: /* fill numa mode here */
+ ignore_value(virDomainNumatuneGetMode(def->numa, -1, &tmpmode));
+
+ if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
+ VIR_TYPED_PARAM_INT, tmpmode) < 0)
+ goto cleanup;
+
+ break;
+
+ case 1: /* fill numa nodeset here */
+ nodeset = virDomainNumatuneFormatNodeset(def->numa, autoNodeset, -1);
+
+ if (!nodeset ||
+ virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
+ VIR_TYPED_PARAM_STRING, nodeset) < 0)
+ goto cleanup;
+
+ nodeset = NULL;
+ break;
+
+ /* coverity[dead_error_begin] */
+ default:
+ break;
+ /* should not hit here */
+ }
+ }
+
+ if (*nparams > CH_NB_NUMA_PARAM)
+ *nparams = CH_NB_NUMA_PARAM;
+ ret = 0;
+
+ cleanup:
+ virDomainObjEndAPI(&vm);
+ return ret;
+}
+
+static int
+chDomainSetNumaParamsLive(virDomainObj *vm,
+ virBitmap *nodeset)
+{
+ virCgroup *cgroup_temp = NULL;
+ virCHDomainObjPrivate *priv = vm->privateData;
+ g_autofree char *nodeset_str = NULL;
+ virDomainNumatuneMemMode mode;
+ size_t i = 0;
+ int ret = -1;
+
+ if (virDomainNumatuneGetMode(vm->def->numa, -1, &mode) == 0 &&
+ mode != VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("change of nodeset for running domain "
+ "requires strict numa mode"));
+ goto cleanup;
+ }
+
+ if (!virNumaNodesetIsAvailable(nodeset))
+ goto cleanup;
+
+ /* Ensure the cpuset string is formatted before passing to cgroup */
+ if (!(nodeset_str = virBitmapFormat(nodeset)))
+ goto cleanup;
+
+ if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
+ false, &cgroup_temp) < 0 ||
+ virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+ goto cleanup;
+ virCgroupFree(cgroup_temp);
+
+ for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
+ virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, i);
+
+ if (!vcpu->online)
+ continue;
+
+ if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i,
+ false, &cgroup_temp) < 0 ||
+ virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+ goto cleanup;
+ virCgroupFree(cgroup_temp);
+ }
+
+ for (i = 0; i < vm->def->niothreadids; i++) {
+ if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
+ vm->def->iothreadids[i]->iothread_id,
+ false, &cgroup_temp) < 0 ||
+ virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+ goto cleanup;
+ virCgroupFree(cgroup_temp);
+ }
+
+ /* set nodeset for root cgroup */
+ if (virCgroupSetCpusetMems(priv->cgroup, nodeset_str) < 0)
+ goto cleanup;
+
+ ret = 0;
+ cleanup:
+ virCgroupFree(cgroup_temp);
+
+ return ret;
+}
+
+static int
+chDomainSetNumaParameters(virDomainPtr dom,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags)
+{
+ virCHDriver *driver = dom->conn->privateData;
+ size_t i;
+ virDomainDef *def;
+ virDomainDef *persistentDef;
+ virDomainObj *vm = NULL;
+ int ret = -1;
+ g_autoptr(virCHDriverConfig) cfg = NULL;
+ virCHDomainObjPrivate *priv;
+ virBitmap *nodeset = NULL;
+ virDomainNumatuneMemMode config_mode;
+ int mode = -1;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+ if (virTypedParamsValidate(params, nparams,
+ VIR_DOMAIN_NUMA_MODE,
+ VIR_TYPED_PARAM_INT,
+ VIR_DOMAIN_NUMA_NODESET,
+ VIR_TYPED_PARAM_STRING,
+ NULL) < 0)
+ return -1;
+
+ if (!(vm = virCHDomainObjFromDomain(dom)))
+ return -1;
+
+ priv = vm->privateData;
+ cfg = virCHDriverGetConfig(driver);
+
+ if (virDomainSetNumaParametersEnsureACL(dom->conn, vm->def, flags) < 0)
+ goto cleanup;
+
+ for (i = 0; i < nparams; i++) {
+ virTypedParameterPtr param = ¶ms[i];
+
+ if (STREQ(param->field, VIR_DOMAIN_NUMA_MODE)) {
+ mode = param->value.i;
+
+ if (mode < 0 || mode >= VIR_DOMAIN_NUMATUNE_MEM_LAST) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("unsupported numatune mode: '%d'"),
mode);
+ goto cleanup;
+ }
+
+ } else if (STREQ(param->field, VIR_DOMAIN_NUMA_NODESET)) {
+ if (virBitmapParse(param->value.s, &nodeset,
+ VIR_DOMAIN_CPUMASK_LEN) < 0)
+ goto cleanup;
+
+ if (virBitmapIsAllClear(nodeset)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("Invalid nodeset of 'numatune': %s"),
+ param->value.s);
+ goto cleanup;
+ }
+ }
+ }
+
+ if (virCHDomainObjBeginJob(vm, CH_JOB_MODIFY) < 0)
+ goto cleanup;
+
+ if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
+ goto endjob;
+
+ if (def) {
+ if (!driver->privileged) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("NUMA tuning is not available in session mode"));
+ goto endjob;
+ }
+
+ if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("cgroup cpuset controller is not mounted"));
+ goto endjob;
+ }
+
+ if (mode != -1 &&
+ virDomainNumatuneGetMode(def->numa, -1, &config_mode) == 0 &&
+ config_mode != mode) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("can't change numatune mode for running
domain"));
+ goto endjob;
+ }
+
+ if (nodeset &&
+ chDomainSetNumaParamsLive(vm, nodeset) < 0)
+ goto endjob;
+
+ if (virDomainNumatuneSet(def->numa,
+ def->placement_mode ==
+ VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
+ -1, mode, nodeset) < 0)
+ goto endjob;
+
+ if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
+ goto endjob;
+ }
+
+ /*
+ if (persistentDef) {
+ if (virDomainNumatuneSet(persistentDef->numa,
+ persistentDef->placement_mode ==
+ VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
+ -1, mode, nodeset) < 0)
+ goto endjob;
+
+ if (virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir) <
0)
+ goto endjob;
+ }
+ */
+
+ ret = 0;
+
+ endjob:
+ virCHDomainObjEndJob(vm);
+
+ cleanup:
+ virBitmapFree(nodeset);
+ virDomainObjEndAPI(&vm);
+ return ret;
+}
+
/* Function Tables */
static virHypervisorDriver chHypervisorDriver = {
.name = "CH",
@@ -1364,6 +1640,8 @@ static virHypervisorDriver chHypervisorDriver = {
.domainPinVcpu = chDomainPinVcpu, /* 7.9.0 */
.domainPinVcpuFlags = chDomainPinVcpuFlags, /* 7.9.0 */
.nodeGetCPUMap = chNodeGetCPUMap, /* 7.9.0 */
+ .domainSetNumaParameters = chDomainSetNumaParameters, /* 7.9.0 */
+ .domainGetNumaParameters = chDomainGetNumaParameters, /* 7.9.0 */
};
static virConnectDriver chConnectDriver = {
--
2.27.0