---
src/qemu/qemu_driver.c | 64 +++++++++++++++++++++++++++++++++++++++---------
1 files changed, 52 insertions(+), 12 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f06dcea..1c71962 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4651,37 +4651,59 @@ cleanup:
return ret;
}
-static int qemuSetSchedulerParameters(virDomainPtr dom,
- virSchedParameterPtr params,
- int nparams)
+static int qemuSetSchedulerParametersFlags(virDomainPtr dom,
+ virSchedParameterPtr params,
+ int nparams,
+ unsigned int flags)
{
struct qemud_driver *driver = dom->conn->privateData;
int i;
virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
+ virDomainDefPtr persistentDef = NULL;
int ret = -1;
- qemuDriverLock(driver);
+ virCheckFlags(VIR_DOMAIN_SCHED_PARAMS_LIVE |
+ VIR_DOMAIN_SCHED_PARAMS_PERSISTENT, -1);
+
if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("cgroup CPU controller is not
mounted"));
goto cleanup;
}
+ qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemuDriverUnlock(driver);
if (vm == NULL) {
- qemuReportError(VIR_ERR_INTERNAL_ERROR,
- _("No such domain %s"), dom->uuid);
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemuReportError(VIR_ERR_NO_DOMAIN,
+ _("No domain with uuid: %s"), uuidstr);
goto cleanup;
}
+ /* Could find the cgroup for domain implies the domain is running. */
if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
{
qemuReportError(VIR_ERR_INTERNAL_ERROR,
- _("cannot find cgroup for domain %s"),
vm->def->name);
+ _("cannot find cgroup for domain %s"),
vm->def->name);
goto cleanup;
}
+ if (qemuDomainObjBeginJob(vm) < 0)
+ goto cleanup;
+
+ if (flags & VIR_DOMAIN_SCHED_PARAMS_PERSISTENT) {
+ if (!vm->persistent) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("cannot change persistent config of a transient
domain"));
+ goto endjob;
+ }
+ if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
+ goto endjob;
+ }
+
for (i = 0; i < nparams; i++) {
virSchedParameterPtr param = ¶ms[i];
@@ -4690,25 +4712,35 @@ static int qemuSetSchedulerParameters(virDomainPtr dom,
if (param->type != VIR_DOMAIN_SCHED_FIELD_ULLONG) {
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
_("invalid type for cpu_shares tunable, expected a
'ullong'"));
- goto cleanup;
+ goto endjob;
}
rc = virCgroupSetCpuShares(group, params[i].value.ul);
if (rc != 0) {
virReportSystemError(-rc, "%s",
- _("unable to set cpu shares tunable"));
- goto cleanup;
+ _("unable to set cpu shares tunable"));
+ goto endjob;
}
vm->def->cputune.shares = params[i].value.ul;
+
+ if (flags & VIR_DOMAIN_SCHED_PARAMS_PERSISTENT) {
+ persistentDef->cputune.shares = params[i].value.ul;
+ ret = virDomainSaveConfig(driver->configDir, persistentDef);
+ goto endjob;
+ }
} else {
qemuReportError(VIR_ERR_INVALID_ARG,
_("Invalid parameter `%s'"), param->field);
- goto cleanup;
+ goto endjob;
}
}
ret = 0;
+endjob:
+ if (qemuDomainObjEndJob(vm) == 0)
+ vm = NULL;
+
cleanup:
virCgroupFree(&group);
if (vm)
@@ -4717,6 +4749,14 @@ cleanup:
return ret;
}
+static int qemuSetSchedulerParameters(virDomainPtr dom,
+ virSchedParameterPtr params,
+ int nparams)
+{
+ return qemuSetSchedulerParametersFlags(dom, params, nparams,
+ VIR_DOMAIN_SCHED_PARAMS_LIVE);
+}
+
static int qemuGetSchedulerParameters(virDomainPtr dom,
virSchedParameterPtr params,
int *nparams)
@@ -6924,7 +6964,7 @@ static virDriver qemuDriver = {
qemuGetSchedulerType, /* domainGetSchedulerType */
qemuGetSchedulerParameters, /* domainGetSchedulerParameters */
qemuSetSchedulerParameters, /* domainSetSchedulerParameters */
- NULL, /* domainSetSchedulerParametersFlags */
+ qemuSetSchedulerParametersFlags, /* domainSetSchedulerParametersFlags */
NULL, /* domainMigratePrepare (v1) */
qemudDomainMigratePerform, /* domainMigratePerform */
NULL, /* domainMigrateFinish */
--
1.7.4