+Wed Oct 8 08:29:25 PDT 2008 Dan Smith <danms@us.ibm.com>
+ * 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 <veillard@redhat.com>
* src/cgroup.c: use safewrite()
with all the same limitations. Open network connections may be
severed upon restore, as TCP timeouts may have expired.
+=item B<schedinfo> optional I<--set> B<parameter=value> I<domain-id>
+
=item B<schedinfo> optional I<--weight> B<number> optional I<--cap> B<number> I<domain-id>
-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<Note>: The weight and cap parameters are defined only for the
+XEN_CREDIT scheduler and are now I<DEPRECATED>.
=item B<setmem> I<domain-id> B<kilobytes>
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)
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;
+
+ if (asprintf(&strval, "%" PRIi64, value) == -1)
+ return -ENOMEM;
+
+ rc = virCgroupSetValueStr(group, key, strval);
+
+ VIR_FREE(strval);
+
+ return rc;
+}
+
+static int virCgroupGetValueI64(virCgroupPtr group,
+ const char *key,
+ int64_t *value)
{
char *strval = NULL;
int rc = 0;
if (rc != 0)
goto out;
- if (sscanf(strval, "%" SCNu64, value) != 1)
+ if (sscanf(strval, "%" SCNi64, value) != 1)
rc = -EINVAL;
out:
VIR_FREE(strval);
return rc;
}
+#endif
-static int virCgroupGetValueI64(virCgroupPtr group,
+static int virCgroupGetValueU64(virCgroupPtr group,
const char *key,
- int64_t *value)
+ uint64_t *value)
{
char *strval = NULL;
int rc = 0;
if (rc != 0)
goto out;
- if (sscanf(strval, "%" SCNi64, value) != 1)
+ if (sscanf(strval, "%" SCNu64, value) != 1)
rc = -EINVAL;
out:
VIR_FREE(strval);
return rc;
}
-#endif
static int _virCgroupInherit(const char *path,
const char *key)
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);
+}
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);
#include <unistd.h>
#include <wait.h>
+#include "internal.h"
#include "lxc_conf.h"
#include "lxc_container.h"
#include "lxc_driver.h"
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 */
NULL, /* domainDetachDevice */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
- NULL, /* domainGetSchedulerType */
- NULL, /* domainGetSchedulerParameters */
- NULL, /* domainSetSchedulerParameters */
+ lxcGetSchedulerType, /* domainGetSchedulerType */
+ lxcGetSchedulerParameters, /* domainGetSchedulerParameters */
+ lxcSetSchedulerParameters, /* domainSetSchedulerParameters */
NULL, /* domainMigratePrepare */
NULL, /* domainMigratePerform */
NULL, /* domainMigrateFinish */
NULL, /* getFreeMemory */
};
-
static virStateDriver lxcStateDriver = {
.initialize = lxcStartup,
.cleanup = lxcShutdown,
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}
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;
int nr_inputparams = 0;
int inputparams = 0;
int weightfound = 0;
+ int setfound = 0;
int weight = 0;
int capfound = 0;
int cap = 0;
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) {
}
}
+ 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;
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);
}
cleanup:
free(params);
+ free(param_name);
virDomainFree(dom);
return ret_val;
}