static void qemuRestoreCgroupState(virDomainObjPtr vm) { char *mem_mask = NULL; char *nodeset = NULL; int empty = -1; qemuDomainObjPrivatePtr priv = vm->privateData; size_t i = 0; virBitmapPtr all_nodes; virCgroupPtr cgroup_temp = NULL; if (!virNumaIsAvailable() || !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) return; if (!(all_nodes = virNumaGetHostMemoryNodeset())) goto error; if (!(mem_mask = virBitmapFormat(all_nodes))) goto error; if ((empty = virCgroupHasEmptyTasks(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) <= 0) goto error; if (virCgroupSetCpusetMems(priv->cgroup, mem_mask) < 0) goto error; for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) { virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(vm->def, i); if (!vcpu->online) continue; if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i, false, &cgroup_temp) < 0 || virCgroupSetCpusetMemoryMigrate(cgroup_temp, true) < 0 || virCgroupGetCpusetMems(cgroup_temp, &nodeset) < 0 || virCgroupSetCpusetMems(cgroup_temp, nodeset) < 0) goto cleanup; VIR_FREE(nodeset); 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 || virCgroupSetCpusetMemoryMigrate(cgroup_temp, true) < 0 || virCgroupGetCpusetMems(cgroup_temp, &nodeset) < 0 || virCgroupSetCpusetMems(cgroup_temp, nodeset) < 0) goto cleanup; VIR_FREE(nodeset); virCgroupFree(&cgroup_temp); } if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0, false, &cgroup_temp) < 0 || virCgroupSetCpusetMemoryMigrate(cgroup_temp, true) < 0 || virCgroupGetCpusetMems(cgroup_temp, &nodeset) < 0 || virCgroupSetCpusetMems(cgroup_temp, nodeset) < 0) goto cleanup; cleanup: VIR_FREE(mem_mask); VIR_FREE(nodeset); virBitmapFree(all_nodes); virCgroupFree(&cgroup_temp); return; error: virResetLastError(); VIR_DEBUG("Couldn't restore cgroups to meaningful state"); goto cleanup; }
int lxctoolsReadConfig(struct lxc_container* cont, virDomainDefPtr def) { char* item_str = NULL; virNodeInfoPtr nodeinfo = NULL; lxctoolsConffilePtr conffile = NULL; if (VIR_ALLOC(nodeinfo) < 0) { goto error; } if (virCapabilitiesGetNodeInfo(nodeinfo) < 0) { goto error; } if (VIR_ALLOC(conffile) < 0) goto error; if (lxctoolsConffileRead(conffile, cont->config_file_name(cont)) < 0) { virReportError(VIR_ERR_OPERATION_FAILED, "'%s'", _("failed to read conffile")); goto error; } if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.arch")) == NULL) { goto error; } if (item_str[0] != '\0') { if (strcmp(item_str, "x86") == 0 || strcmp(item_str, "i686") == 0) { def->os.arch = VIR_ARCH_I686; } else if (strcmp(item_str, "x86_64") == 0 || strcmp(item_str, "amd64") == 0) { def->os.arch = VIR_ARCH_X86_64; } else { virReportError(VIR_ERR_OPERATION_FAILED, "Unknown architecture '%s'.", item_str); goto error; } } VIR_FREE(item_str); item_str = NULL; if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.cpuset.cpus")) == NULL){ goto error; } if (item_str[0] == '\0') { if (virDomainDefSetVcpusMax(def, nodeinfo->cpus, NULL) < 0) goto error; def->cpumask = virBitmapNew(nodeinfo->cpus); virBitmapSetAll(def->cpumask); } else { int cpunum; if ( (cpunum = virBitmapParse(item_str, &def->cpumask, nodeinfo->cpus) ) < 0) { goto error; } if (virDomainDefSetVcpusMax(def, cpunum, NULL) < 0) goto error; } if (virDomainDefSetVcpus(def, virDomainDefGetVcpusMax(def)) < 0) goto error; VIR_FREE(item_str); item_str = NULL; if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.cpu.shares")) == NULL) { goto error; } if (item_str[0] != '\0') { unsigned long shares; sscanf(item_str, "%lu", &shares); def->cputune.shares = shares; def->cputune.sharesSpecified = true; } VIR_FREE(item_str); item_str = NULL; if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.cpu.cfs_period_us")) == NULL) { goto error; } if (item_str[0] != '\0') { unsigned long long period; sscanf(item_str, "%llu", &period); def->cputune.period = period; } VIR_FREE(item_str); item_str = NULL; if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.cpu.cfs_quota_us")) == NULL) { goto error; } if (item_str[0] != '\0') { long long quota; sscanf(item_str, "%llu", "a); def->cputune.quota = quota; } VIR_FREE(item_str); item_str = NULL; if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.memory.limit_in_bytes")) == NULL) { goto error; } if (item_str[0] == '\0') { virDomainDefSetMemoryTotal(def, nodeinfo->memory); } else { virDomainDefSetMemoryTotal(def, memToULL(item_str)); } def->mem.cur_balloon = virDomainDefGetMemoryTotal(def); // def->mem.max_memory = nodeinfo->memory; // def->mem.memory_slots = 1; //maybe delete max_memory alltogether VIR_FREE(item_str); item_str = NULL; if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.memory.soft_limit_in_bytes")) == NULL) { goto error; } if (item_str[0] != '\0') { def->mem.soft_limit = memToULL(item_str); } VIR_FREE(item_str); item_str = NULL; if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.cpuset.mems")) == NULL) { goto error; } if (item_str[0] != '\0') { virBitmapPtr nodeset; if (virBitmapParse(item_str, &nodeset, nodeinfo->nodes) < 0) { goto error; } if (virDomainNumatuneSet(def->numa, true, VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT, VIR_DOMAIN_NUMATUNE_MEM_STRICT, nodeset) < 0 ) { goto error; } } VIR_FREE(item_str); item_str = NULL; if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.include")) == NULL) { goto error; } //lxc.include is optional! if (item_str[0] != '\0') { def->metadata = xmlNewNode(NULL, (const xmlChar*) "metadata"); xmlNewTextChild(def->metadata, NULL, (const xmlChar*) (const xmlChar*)"lxctools:include", (const xmlChar*)item_str); } VIR_FREE(item_str); item_str = NULL; if (lxctoolsReadFSConfig(conffile, def) < 0) goto error; if (lxctoolsReadNetConfig(cont, def) < 0) goto error; return 0; error: VIR_FREE(item_str); VIR_FREE(nodeinfo); return -1; }