From 6c504d6a7ca556e4fe638046df9c482b2c88df1a Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Wed, 8 Oct 2008 16:28:48 +0000 Subject: [PATCH] Add LXC scheduling parameters and support in virsh schedinfo --- ChangeLog | 5 +++ docs/virsh.pod | 10 +++-- src/cgroup.c | 68 +++++++++++++++++++--------------- src/cgroup.h | 3 ++ src/lxc_driver.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++-- src/virsh.c | 36 +++++++++++++++++- 6 files changed, 179 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5b1240068c..beee23d4cd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed Oct 8 08:29:25 PDT 2008 Dan Smith + * src/cgroup.c src/cgroup.h: Add cpu shares manipulation + * src/lxc_driver.c: Add scheduler parameters interface for cpu shares + * src/virsh.c: Add generic scheduler parameter interface + Wed Oct 8 15:42:44 CEST 2008 Daniel Veillard * src/cgroup.c: use safewrite() diff --git a/docs/virsh.pod b/docs/virsh.pod index 0715e5c524..f59be4511f 100644 --- a/docs/virsh.pod +++ b/docs/virsh.pod @@ -318,12 +318,14 @@ This is roughly equivalent to doing a hibernate on a running computer, with all the same limitations. Open network connections may be severed upon restore, as TCP timeouts may have expired. +=item B optional I<--set> B I + =item B optional I<--weight> B optional I<--cap> B I -Allows to show (and set) the domain scheduler parameters. This is currently -only defined for XEN_CREDIT scheduler, and the optional weight and cap -arguments allows to set the associated parameters in that scheduler if -provided. +Allows to show (and set) the domain scheduler parameters. + +B: The weight and cap parameters are defined only for the +XEN_CREDIT scheduler and are now I. =item B I B diff --git a/src/cgroup.c b/src/cgroup.c index f1801c89ce..36e2907b03 100644 --- a/src/cgroup.c +++ b/src/cgroup.c @@ -224,26 +224,6 @@ static int virCgroupSetValueU64(virCgroupPtr group, return rc; } -#if 0 -/* This is included for completeness, but not yet used */ - -static int virCgroupSetValueI64(virCgroupPtr group, - const char *key, - int64_t value) -{ - char *strval = NULL; - int rc; - - if (asprintf(&strval, "%" PRIi64, value) == -1) - return -ENOMEM; - - rc = virCgroupSetValueStr(group, key, strval); - - VIR_FREE(strval); - - return rc; -} - static int virCgroupGetValueStr(virCgroupPtr group, const char *key, char **value) @@ -293,20 +273,21 @@ out: return rc; } -static int virCgroupGetValueU64(virCgroupPtr group, +#if 0 +/* This is included for completeness, but not yet used */ + +static int virCgroupSetValueI64(virCgroupPtr group, const char *key, - uint64_t *value) + int64_t value) { char *strval = NULL; - int rc = 0; + int rc; - rc = virCgroupGetValueStr(group, key, &strval); - if (rc != 0) - goto out; + if (asprintf(&strval, "%" PRIi64, value) == -1) + return -ENOMEM; + + rc = virCgroupSetValueStr(group, key, strval); - if (sscanf(strval, "%" SCNu64, value) != 1) - rc = -EINVAL; -out: VIR_FREE(strval); return rc; @@ -332,6 +313,25 @@ out: } #endif +static int virCgroupGetValueU64(virCgroupPtr group, + const char *key, + uint64_t *value) +{ + char *strval = NULL; + int rc = 0; + + rc = virCgroupGetValueStr(group, key, &strval); + if (rc != 0) + goto out; + + if (sscanf(strval, "%" SCNu64, value) != 1) + rc = -EINVAL; +out: + VIR_FREE(strval); + + return rc; +} + static int _virCgroupInherit(const char *path, const char *key) { @@ -760,3 +760,13 @@ out: return rc; } + +int virCgroupSetCpuShares(virCgroupPtr group, unsigned long shares) +{ + return virCgroupSetValueU64(group, "cpu.shares", (uint64_t)shares); +} + +int virCgroupGetCpuShares(virCgroupPtr group, unsigned long *shares) +{ + return virCgroupGetValueU64(group, "cpu.shares", (uint64_t *)shares); +} diff --git a/src/cgroup.h b/src/cgroup.h index 7aca3d095e..193da63f4e 100644 --- a/src/cgroup.h +++ b/src/cgroup.h @@ -36,6 +36,9 @@ int virCgroupAllowDevice(virCgroupPtr group, int major, int minor); +int virCgroupSetCpuShares(virCgroupPtr group, unsigned long shares); +int virCgroupGetCpuShares(virCgroupPtr group, unsigned long *shares); + int virCgroupRemove(virCgroupPtr group); void virCgroupFree(virCgroupPtr *group); diff --git a/src/lxc_driver.c b/src/lxc_driver.c index 64c3d21941..30c3cab064 100644 --- a/src/lxc_driver.c +++ b/src/lxc_driver.c @@ -35,6 +35,7 @@ #include #include +#include "internal.h" #include "lxc_conf.h" #include "lxc_container.h" #include "lxc_driver.h" @@ -1144,6 +1145,94 @@ static int lxcVersion(virConnectPtr conn, unsigned long *version) return 0; } +static char *lxcGetSchedulerType(virDomainPtr domain, int *nparams) +{ + if (nparams) + *nparams = 1; + + return strdup("posix"); +} + +static int lxcSetSchedulerParameters(virDomainPtr _domain, + virSchedParameterPtr params, + int nparams) +{ + int i; + int rc; + virCgroupPtr group; + virDomainObjPtr domain; + + if (virCgroupHaveSupport() != 0) + return 0; + + domain = virDomainFindByUUID(lxc_driver->domains, _domain->uuid); + if (domain == NULL) { + lxcError(NULL, _domain, VIR_ERR_INTERNAL_ERROR, + _("No such domain %s"), _domain->uuid); + return -EINVAL; + } + + rc = virCgroupForDomain(domain->def, "lxc", &group); + if (rc != 0) + return rc; + + for (i = 0; i < nparams; i++) { + virSchedParameterPtr param = ¶ms[i]; + + if (STREQ(param->field, "cpu_shares")) { + rc = virCgroupSetCpuShares(group, params[i].value.ui); + } else { + lxcError(NULL, _domain, VIR_ERR_INVALID_ARG, + _("Invalid parameter `%s'"), param->field); + rc = -ENOENT; + goto out; + } + } + + rc = 0; +out: + virCgroupFree(&group); + + return rc; +} + +static int lxcGetSchedulerParameters(virDomainPtr _domain, + virSchedParameterPtr params, + int *nparams) +{ + int rc = 0; + virCgroupPtr group; + virDomainObjPtr domain; + + if (virCgroupHaveSupport() != 0) + return 0; + + if ((*nparams) != 1) { + lxcError(NULL, _domain, VIR_ERR_INVALID_ARG, + _("Invalid parameter count")); + return -1; + } + + domain = virDomainFindByUUID(lxc_driver->domains, _domain->uuid); + if (domain == NULL) { + lxcError(NULL, _domain, VIR_ERR_INTERNAL_ERROR, + _("No such domain %s"), _domain->uuid); + return -ENOENT; + } + + rc = virCgroupForDomain(domain->def, "lxc", &group); + if (rc != 0) + return rc; + + rc = virCgroupGetCpuShares(group, (unsigned long *)¶ms[0].value.ul); + strncpy(params[0].field, "cpu_shares", sizeof(params[0].field)); + params[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG; + + virCgroupFree(&group); + + return rc; +} + /* Function Tables */ static virDriver lxcDriver = { VIR_DRV_LXC, /* the number virDrvNo */ @@ -1193,9 +1282,9 @@ static virDriver lxcDriver = { NULL, /* domainDetachDevice */ NULL, /* domainGetAutostart */ NULL, /* domainSetAutostart */ - NULL, /* domainGetSchedulerType */ - NULL, /* domainGetSchedulerParameters */ - NULL, /* domainSetSchedulerParameters */ + lxcGetSchedulerType, /* domainGetSchedulerType */ + lxcGetSchedulerParameters, /* domainGetSchedulerParameters */ + lxcSetSchedulerParameters, /* domainSetSchedulerParameters */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ @@ -1207,7 +1296,6 @@ static virDriver lxcDriver = { NULL, /* getFreeMemory */ }; - static virStateDriver lxcStateDriver = { .initialize = lxcStartup, .cleanup = lxcShutdown, diff --git a/src/virsh.c b/src/virsh.c index 00f928fec5..eaed61d759 100644 --- a/src/virsh.c +++ b/src/virsh.c @@ -1112,6 +1112,7 @@ static const vshCmdInfo info_schedinfo[] = { static const vshCmdOptDef opts_schedinfo[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")}, + {"set", VSH_OT_STRING, VSH_OFLAG_NONE, gettext_noop("parameter=value")}, {"weight", VSH_OT_INT, VSH_OFLAG_NONE, gettext_noop("weight for XEN_CREDIT")}, {"cap", VSH_OT_INT, VSH_OFLAG_NONE, gettext_noop("cap for XEN_CREDIT")}, {NULL, 0, 0, NULL} @@ -1121,6 +1122,9 @@ static int cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) { char *schedulertype; + char *set; + char *param_name = NULL; + long long int param_value = 0; virDomainPtr dom; virSchedParameterPtr params = NULL; int i, ret; @@ -1128,6 +1132,7 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) int nr_inputparams = 0; int inputparams = 0; int weightfound = 0; + int setfound = 0; int weight = 0; int capfound = 0; int cap = 0; @@ -1141,7 +1146,7 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL))) return FALSE; - /* Currently supports Xen Credit only */ + /* Deprecated Xen-only options */ if(vshCommandOptBool(cmd, "weight")) { weight = vshCommandOptInt(cmd, "weight", &weightfound); if (!weightfound) { @@ -1162,6 +1167,25 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) } } + if(vshCommandOptBool(cmd, "set")) { + set = vshCommandOptString(cmd, "set", &setfound); + if (!setfound) { + vshError(ctl, FALSE, "%s", _("Error getting param")); + goto cleanup; + } + + param_name = vshMalloc(ctl, strlen(set) + 1); + if (param_name == NULL) + goto cleanup; + + if (sscanf(set, "%[^=]=%i", param_name, ¶m_value) != 2) { + vshError(ctl, FALSE, "%s", _("Invalid value of param")); + goto cleanup; + } + + nr_inputparams++; + } + params = vshMalloc(ctl, sizeof (virSchedParameter) * nr_inputparams); if (params == NULL) { goto cleanup; @@ -1180,7 +1204,14 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) params[inputparams].value.ui = cap; inputparams++; } - /* End Currently supports Xen Credit only */ + /* End Deprecated Xen-only options */ + + if (setfound) { + strncpy(params[inputparams].field,param_name,sizeof(params[0].field)); + params[inputparams].type = VIR_DOMAIN_SCHED_FIELD_LLONG; + params[inputparams].value.l = param_value; + inputparams++; + } assert (inputparams == nr_inputparams); @@ -1247,6 +1278,7 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) } cleanup: free(params); + free(param_name); virDomainFree(dom); return ret_val; }