forked from pool/libvirt
This commit is contained in:
parent
d045108cb4
commit
92cce1a7b8
822
cgroup.patch
Normal file
822
cgroup.patch
Normal file
@ -0,0 +1,822 @@
|
||||
# HG changeset patch
|
||||
# User danms
|
||||
# Date 1223056682 0
|
||||
# Node ID 64f19f607bc6837fe2411cfdb2942b13ce8902c1
|
||||
# Parent a28490b116b0430aa0d4f579bba57d52793312ed
|
||||
[r2008-10-03 17:58:02 by danms] Add forgotten cgroup.{c,h} and ChangeLog
|
||||
|
||||
Index: libvirt-0.4.6/src/cgroup.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ libvirt-0.4.6/src/cgroup.c
|
||||
@@ -0,0 +1,762 @@
|
||||
+/*
|
||||
+ * cgroup.c: Tools for managing cgroups
|
||||
+ *
|
||||
+ * Copyright IBM Corp. 2008
|
||||
+ *
|
||||
+ * See COPYING.LIB for the License of this software
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Dan Smith <danms@us.ibm.com>
|
||||
+ */
|
||||
+#include <config.h>
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdint.h>
|
||||
+#include <inttypes.h>
|
||||
+#include <mntent.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <string.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <libgen.h>
|
||||
+
|
||||
+#include "internal.h"
|
||||
+#include "util.h"
|
||||
+#include "memory.h"
|
||||
+#include "cgroup.h"
|
||||
+
|
||||
+#define DEBUG(fmt,...) VIR_DEBUG(__FILE__, fmt, __VA_ARGS__)
|
||||
+#define DEBUG0(msg) VIR_DEBUG(__FILE__, "%s", msg)
|
||||
+
|
||||
+#define CGROUP_MAX_VAL 512
|
||||
+
|
||||
+struct virCgroup {
|
||||
+ char *path;
|
||||
+};
|
||||
+
|
||||
+const char *supported_controllers[] = {
|
||||
+ "memory",
|
||||
+ "devices",
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * virCgroupFree:
|
||||
+ *
|
||||
+ * @group: The group structure to free
|
||||
+ */
|
||||
+void virCgroupFree(virCgroupPtr *group)
|
||||
+{
|
||||
+ if (*group != NULL) {
|
||||
+ VIR_FREE((*group)->path);
|
||||
+ VIR_FREE(*group);
|
||||
+ *group = NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static virCgroupPtr virCgroupGetMount(const char *controller)
|
||||
+{
|
||||
+ FILE *mounts;
|
||||
+ struct mntent entry;
|
||||
+ char buf[CGROUP_MAX_VAL];
|
||||
+ virCgroupPtr root = NULL;
|
||||
+
|
||||
+ if (VIR_ALLOC(root) != 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ mounts = fopen("/proc/mounts", "r");
|
||||
+ if (mounts == NULL) {
|
||||
+ DEBUG0("Unable to open /proc/mounts: %m");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
|
||||
+ if (STREQ(entry.mnt_type, "cgroup") &&
|
||||
+ (strstr(entry.mnt_opts, controller))) {
|
||||
+ root->path = strdup(entry.mnt_dir);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ DEBUG("Mount for %s is %s\n", controller, root->path);
|
||||
+
|
||||
+ if (root->path == NULL) {
|
||||
+ DEBUG0("Did not find cgroup mount");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ fclose(mounts);
|
||||
+
|
||||
+ return root;
|
||||
+err:
|
||||
+ virCgroupFree(&root);
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * virCgroupHaveSupport:
|
||||
+ *
|
||||
+ * Returns 0 if support is present, negative if not
|
||||
+ */
|
||||
+int virCgroupHaveSupport(void)
|
||||
+{
|
||||
+ virCgroupPtr root;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; supported_controllers[i] != NULL; i++) {
|
||||
+ root = virCgroupGetMount(supported_controllers[i]);
|
||||
+ if (root == NULL)
|
||||
+ return -1;
|
||||
+ virCgroupFree(&root);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int virCgroupPathOfGroup(const char *group,
|
||||
+ const char *controller,
|
||||
+ char **path)
|
||||
+{
|
||||
+ virCgroupPtr root = NULL;
|
||||
+ int rc = 0;
|
||||
+
|
||||
+ root = virCgroupGetMount(controller);
|
||||
+ if (root == NULL) {
|
||||
+ rc = -ENOTDIR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (asprintf(path, "%s/%s", root->path, group) == -1)
|
||||
+ rc = -ENOMEM;
|
||||
+out:
|
||||
+ virCgroupFree(&root);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int virCgroupPathOf(const char *grppath,
|
||||
+ const char *key,
|
||||
+ char **path)
|
||||
+{
|
||||
+ virCgroupPtr root;
|
||||
+ int rc = 0;
|
||||
+ char *controller = NULL;
|
||||
+
|
||||
+ if (strchr(key, '.') == NULL)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (sscanf(key, "%a[^.]", &controller) != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ root = virCgroupGetMount(controller);
|
||||
+ if (root == NULL) {
|
||||
+ rc = -ENOTDIR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (asprintf(path, "%s/%s/%s", root->path, grppath, key) == -1)
|
||||
+ rc = -ENOMEM;
|
||||
+out:
|
||||
+ virCgroupFree(&root);
|
||||
+ VIR_FREE(controller);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int virCgroupSetValueStr(virCgroupPtr group,
|
||||
+ const char *key,
|
||||
+ const char *value)
|
||||
+{
|
||||
+ int fd = -1;
|
||||
+ int rc = 0;
|
||||
+ char *keypath = NULL;
|
||||
+
|
||||
+ rc = virCgroupPathOf(group->path, key, &keypath);
|
||||
+ if (rc != 0)
|
||||
+ return rc;
|
||||
+
|
||||
+ fd = open(keypath, O_WRONLY);
|
||||
+ if (fd < 0) {
|
||||
+ DEBUG("Unable to open %s: %m", keypath);
|
||||
+ rc = -ENOENT;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ DEBUG("Writing '%s' to '%s'", value, keypath);
|
||||
+
|
||||
+ rc = safewrite(fd, value, strlen(value));
|
||||
+ if (rc < 0) {
|
||||
+ DEBUG("Failed to write value '%s': %m", value);
|
||||
+ rc = -errno;
|
||||
+ goto out;
|
||||
+ } else if (rc != strlen(value)) {
|
||||
+ DEBUG("Short write of value '%s'", value);
|
||||
+ rc = -ENOSPC;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ rc = 0;
|
||||
+out:
|
||||
+ VIR_FREE(keypath);
|
||||
+ close(fd);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int virCgroupSetValueU64(virCgroupPtr group,
|
||||
+ const char *key,
|
||||
+ uint64_t value)
|
||||
+{
|
||||
+ char *strval = NULL;
|
||||
+ int rc;
|
||||
+
|
||||
+ if (asprintf(&strval, "%" PRIu64, value) == -1)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ rc = virCgroupSetValueStr(group, key, strval);
|
||||
+
|
||||
+ VIR_FREE(strval);
|
||||
+
|
||||
+ 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)
|
||||
+{
|
||||
+ int fd = -1;
|
||||
+ int rc;
|
||||
+ char *keypath = NULL;
|
||||
+ char buf[CGROUP_MAX_VAL];
|
||||
+
|
||||
+ memset(buf, 0, sizeof(buf));
|
||||
+
|
||||
+ rc = virCgroupPathOf(group->path, key, &keypath);
|
||||
+ if (rc != 0) {
|
||||
+ DEBUG("No path of %s, %s", group->path, key);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ fd = open(keypath, O_RDONLY);
|
||||
+ if (fd < 0) {
|
||||
+ DEBUG("Unable to open %s: %m", keypath);
|
||||
+ rc = -ENOENT;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ rc = saferead(fd, buf, sizeof(buf));
|
||||
+ if (rc < 0) {
|
||||
+ DEBUG("Failed to read %s: %m\n", keypath);
|
||||
+ rc = -errno;
|
||||
+ goto out;
|
||||
+ } else if (rc == 0) {
|
||||
+ DEBUG("Short read of %s\n", keypath);
|
||||
+ rc = -EIO;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ *value = strdup(buf);
|
||||
+ if (*value == NULL) {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ rc = 0;
|
||||
+out:
|
||||
+ VIR_FREE(keypath);
|
||||
+ close(fd);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+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 virCgroupGetValueI64(virCgroupPtr group,
|
||||
+ const char *key,
|
||||
+ int64_t *value)
|
||||
+{
|
||||
+ char *strval = NULL;
|
||||
+ int rc = 0;
|
||||
+
|
||||
+ rc = virCgroupGetValueStr(group, key, &strval);
|
||||
+ if (rc != 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (sscanf(strval, "%" SCNi64, value) != 1)
|
||||
+ rc = -EINVAL;
|
||||
+out:
|
||||
+ VIR_FREE(strval);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static int _virCgroupInherit(const char *path,
|
||||
+ const char *key)
|
||||
+{
|
||||
+ int rc = 0;
|
||||
+ int fd = -1;
|
||||
+ char buf[CGROUP_MAX_VAL];
|
||||
+ char *keypath = NULL;
|
||||
+ char *pkeypath = NULL;
|
||||
+
|
||||
+ memset(buf, 0, sizeof(buf));
|
||||
+
|
||||
+ if (asprintf(&keypath, "%s/%s", path, key) == -1) {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (access(keypath, F_OK) != 0) {
|
||||
+ DEBUG("Group %s has no key %s\n", path, key);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (asprintf(&pkeypath, "%s/../%s", path, key) == -1) {
|
||||
+ rc = -ENOMEM;
|
||||
+ VIR_FREE(keypath);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ fd = open(pkeypath, O_RDONLY);
|
||||
+ if (fd < 0) {
|
||||
+ rc = -errno;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (saferead(fd, buf, sizeof(buf)) <= 0) {
|
||||
+ rc = -errno;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ close(fd);
|
||||
+
|
||||
+ fd = open(keypath, O_WRONLY);
|
||||
+ if (fd < 0) {
|
||||
+ rc = -errno;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (safewrite(fd, buf, strlen(buf)) != strlen(buf)) {
|
||||
+ rc = -errno;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ VIR_FREE(keypath);
|
||||
+ VIR_FREE(pkeypath);
|
||||
+ close(fd);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int virCgroupInherit(const char *grppath)
|
||||
+{
|
||||
+ int i;
|
||||
+ int rc = 0;
|
||||
+ const char *inherit_values[] = {
|
||||
+ "cpuset.cpus",
|
||||
+ "cpuset.mems",
|
||||
+ NULL
|
||||
+ };
|
||||
+
|
||||
+ for (i = 0; inherit_values[i] != NULL; i++) {
|
||||
+ const char *key = inherit_values[i];
|
||||
+
|
||||
+ rc = _virCgroupInherit(grppath, key);
|
||||
+ if (rc != 0) {
|
||||
+ DEBUG("inherit of %s failed\n", key);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int virCgroupMakeGroup(const char *name)
|
||||
+{
|
||||
+ int i;
|
||||
+ int rc = 0;
|
||||
+
|
||||
+ for (i = 0; supported_controllers[i] != NULL; i++) {
|
||||
+ char *path = NULL;
|
||||
+ virCgroupPtr root;
|
||||
+
|
||||
+ root = virCgroupGetMount(supported_controllers[i]);
|
||||
+ if (root == NULL)
|
||||
+ continue;
|
||||
+
|
||||
+ rc = virCgroupPathOfGroup(name, supported_controllers[i], &path);
|
||||
+ if (rc != 0) {
|
||||
+ virCgroupFree(&root);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ virCgroupFree(&root);
|
||||
+
|
||||
+ if (access(path, F_OK) != 0) {
|
||||
+ if (mkdir(path, 0655) < 0) {
|
||||
+ rc = -errno;
|
||||
+ VIR_FREE(path);
|
||||
+ break;
|
||||
+ }
|
||||
+ virCgroupInherit(path);
|
||||
+ }
|
||||
+
|
||||
+ VIR_FREE(path);
|
||||
+ }
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int virCgroupRoot(virCgroupPtr *root)
|
||||
+{
|
||||
+ int rc = 0;
|
||||
+ char *grppath = NULL;
|
||||
+
|
||||
+ if (VIR_ALLOC((*root)) != 0) {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ (*root)->path = strdup("libvirt");
|
||||
+ if ((*root)->path == NULL) {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ rc = virCgroupMakeGroup((*root)->path);
|
||||
+out:
|
||||
+ if (rc != 0)
|
||||
+ virCgroupFree(root);
|
||||
+ VIR_FREE(grppath);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int virCgroupNew(virCgroupPtr *parent,
|
||||
+ const char *group,
|
||||
+ virCgroupPtr *newgroup)
|
||||
+{
|
||||
+ int rc = 0;
|
||||
+ char *typpath = NULL;
|
||||
+
|
||||
+ *newgroup = NULL;
|
||||
+
|
||||
+ if (*parent == NULL) {
|
||||
+ rc = virCgroupRoot(parent);
|
||||
+ if (rc != 0)
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if (VIR_ALLOC((*newgroup)) != 0) {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ rc = asprintf(&((*newgroup)->path),
|
||||
+ "%s/%s",
|
||||
+ (*parent)->path,
|
||||
+ group);
|
||||
+ if (rc == -1) {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ rc = 0;
|
||||
+
|
||||
+ return rc;
|
||||
+err:
|
||||
+ virCgroupFree(newgroup);
|
||||
+ *newgroup = NULL;
|
||||
+
|
||||
+ VIR_FREE(typpath);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int virCgroupOpen(virCgroupPtr parent,
|
||||
+ const char *group,
|
||||
+ virCgroupPtr *newgroup)
|
||||
+{
|
||||
+ int rc = 0;
|
||||
+ char *grppath = NULL;
|
||||
+ bool free_parent = (parent == NULL);
|
||||
+
|
||||
+ rc = virCgroupNew(&parent, group, newgroup);
|
||||
+ if (rc != 0)
|
||||
+ goto err;
|
||||
+
|
||||
+ if (free_parent)
|
||||
+ virCgroupFree(&parent);
|
||||
+
|
||||
+ rc = virCgroupPathOfGroup((*newgroup)->path,
|
||||
+ supported_controllers[0],
|
||||
+ &grppath);
|
||||
+ if (rc != 0)
|
||||
+ goto err;
|
||||
+
|
||||
+ if (access(grppath, F_OK) != 0) {
|
||||
+ rc = -ENOENT;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ return rc;
|
||||
+err:
|
||||
+ virCgroupFree(newgroup);
|
||||
+ *newgroup = NULL;
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int virCgroupCreate(virCgroupPtr parent,
|
||||
+ const char *group,
|
||||
+ virCgroupPtr *newgroup)
|
||||
+{
|
||||
+ int rc = 0;
|
||||
+ bool free_parent = (parent == NULL);
|
||||
+
|
||||
+ rc = virCgroupNew(&parent, group, newgroup);
|
||||
+ if (rc != 0) {
|
||||
+ DEBUG0("Unable to allocate new virCgroup structure");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ rc = virCgroupMakeGroup((*newgroup)->path);
|
||||
+ if (rc != 0)
|
||||
+ goto err;
|
||||
+
|
||||
+ if (free_parent)
|
||||
+ virCgroupFree(&parent);
|
||||
+
|
||||
+ return rc;
|
||||
+err:
|
||||
+ virCgroupFree(newgroup);
|
||||
+ *newgroup = NULL;
|
||||
+
|
||||
+ if (free_parent)
|
||||
+ virCgroupFree(&parent);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * virCgroupRemove:
|
||||
+ *
|
||||
+ * @group: The group to be removed
|
||||
+ *
|
||||
+ * Returns: 0 on success
|
||||
+ */
|
||||
+int virCgroupRemove(virCgroupPtr group)
|
||||
+{
|
||||
+ int rc = 0;
|
||||
+ int i;
|
||||
+ char *grppath = NULL;
|
||||
+
|
||||
+ for (i = 0; supported_controllers[i] != NULL; i++) {
|
||||
+ if (virCgroupPathOfGroup(group->path,
|
||||
+ supported_controllers[i],
|
||||
+ &grppath) != 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (rmdir(grppath) != 0)
|
||||
+ rc = -errno;
|
||||
+
|
||||
+ VIR_FREE(grppath);
|
||||
+ }
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * virCgroupAddTask:
|
||||
+ *
|
||||
+ * @group: The cgroup to add a task to
|
||||
+ * @pid: The pid of the task to add
|
||||
+ *
|
||||
+ * Returns: 0 on success
|
||||
+ */
|
||||
+int virCgroupAddTask(virCgroupPtr group, pid_t pid)
|
||||
+{
|
||||
+ int rc = 0;
|
||||
+ int fd = -1;
|
||||
+ int i;
|
||||
+ char *grppath = NULL;
|
||||
+ char *taskpath = NULL;
|
||||
+ char *pidstr = NULL;
|
||||
+
|
||||
+ for (i = 0; supported_controllers[i] != NULL; i++) {
|
||||
+ rc = virCgroupPathOfGroup(group->path,
|
||||
+ supported_controllers[i],
|
||||
+ &grppath);
|
||||
+ if (rc != 0)
|
||||
+ goto done;
|
||||
+
|
||||
+ if (asprintf(&taskpath, "%s/tasks", grppath) == -1) {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ fd = open(taskpath, O_WRONLY);
|
||||
+ if (fd < 0) {
|
||||
+ rc = -errno;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (asprintf(&pidstr, "%lu", (unsigned long)pid) == -1) {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (write(fd, pidstr, strlen(pidstr)) <= 0) {
|
||||
+ rc = -errno;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ done:
|
||||
+ VIR_FREE(grppath);
|
||||
+ VIR_FREE(taskpath);
|
||||
+ VIR_FREE(pidstr);
|
||||
+ close(fd);
|
||||
+
|
||||
+ if (rc != 0)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * virCgroupForDomain:
|
||||
+ *
|
||||
+ * @def: Domain definition to create cgroup for
|
||||
+ * @driverName: Classification of this domain type (e.g., xen, qemu, lxc)
|
||||
+ * @group: Pointer to returned virCgroupPtr
|
||||
+ *
|
||||
+ * Returns 0 on success
|
||||
+ */
|
||||
+int virCgroupForDomain(virDomainDefPtr def,
|
||||
+ const char *driverName,
|
||||
+ virCgroupPtr *group)
|
||||
+{
|
||||
+ int rc;
|
||||
+ virCgroupPtr typegrp = NULL;
|
||||
+
|
||||
+ rc = virCgroupOpen(NULL, driverName, &typegrp);
|
||||
+ if (rc == -ENOENT) {
|
||||
+ rc = virCgroupCreate(NULL, driverName, &typegrp);
|
||||
+ if (rc != 0)
|
||||
+ goto out;
|
||||
+ } else if (rc != 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ rc = virCgroupOpen(typegrp, def->name, group);
|
||||
+ if (rc == -ENOENT)
|
||||
+ rc = virCgroupCreate(typegrp, def->name, group);
|
||||
+out:
|
||||
+ virCgroupFree(&typegrp);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * virCgroupSetMemory:
|
||||
+ *
|
||||
+ * @group: The cgroup to change memory for
|
||||
+ * @kb: The memory amount in kilobytes
|
||||
+ *
|
||||
+ * Returns: 0 on success
|
||||
+ */
|
||||
+int virCgroupSetMemory(virCgroupPtr group, unsigned long kb)
|
||||
+{
|
||||
+ return virCgroupSetValueU64(group,
|
||||
+ "memory.limit_in_bytes",
|
||||
+ kb << 10);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * virCgroupDenyAllDevices:
|
||||
+ *
|
||||
+ * @group: The cgroup to deny devices for
|
||||
+ *
|
||||
+ * Returns: 0 on success
|
||||
+ */
|
||||
+int virCgroupDenyAllDevices(virCgroupPtr group)
|
||||
+{
|
||||
+ return virCgroupSetValueStr(group,
|
||||
+ "devices.deny",
|
||||
+ "a");
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * virCgroupAllowDevice:
|
||||
+ *
|
||||
+ * @group: The cgroup to allow a device for
|
||||
+ * @type: The device type (i.e., 'c' or 'b')
|
||||
+ * @major: The major number of the device
|
||||
+ * @minor: The minor number of the device
|
||||
+ *
|
||||
+ * Returns: 0 on success
|
||||
+ */
|
||||
+int virCgroupAllowDevice(virCgroupPtr group,
|
||||
+ char type,
|
||||
+ int major,
|
||||
+ int minor)
|
||||
+{
|
||||
+ int rc;
|
||||
+ char *devstr = NULL;
|
||||
+
|
||||
+ if (asprintf(&devstr, "%c %i:%i rwm", type, major, minor) == -1) {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ rc = virCgroupSetValueStr(group,
|
||||
+ "devices.allow",
|
||||
+ devstr);
|
||||
+out:
|
||||
+ VIR_FREE(devstr);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
Index: libvirt-0.4.6/src/cgroup.h
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ libvirt-0.4.6/src/cgroup.h
|
||||
@@ -0,0 +1,43 @@
|
||||
+/*
|
||||
+ * cgroup.h: Interface to tools for managing cgroups
|
||||
+ *
|
||||
+ * Copyright IBM Corp. 2008
|
||||
+ *
|
||||
+ * See COPYING.LIB for the License of this software
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Dan Smith <danms@us.ibm.com>
|
||||
+ */
|
||||
+
|
||||
+#ifndef CGROUP_H
|
||||
+#define CGROUP_H
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+struct virCgroup;
|
||||
+typedef struct virCgroup *virCgroupPtr;
|
||||
+
|
||||
+#include "domain_conf.h"
|
||||
+
|
||||
+int virCgroupHaveSupport(void);
|
||||
+
|
||||
+int virCgroupForDomain(virDomainDefPtr def,
|
||||
+ const char *driverName,
|
||||
+ virCgroupPtr *group);
|
||||
+
|
||||
+int virCgroupAddTask(virCgroupPtr group, pid_t pid);
|
||||
+
|
||||
+int virCgroupSetMemory(virCgroupPtr group, unsigned long kb);
|
||||
+
|
||||
+int virCgroupDenyAllDevices(virCgroupPtr group);
|
||||
+
|
||||
+int virCgroupAllowDevice(virCgroupPtr group,
|
||||
+ char type,
|
||||
+ int major,
|
||||
+ int minor);
|
||||
+
|
||||
+int virCgroupRemove(virCgroupPtr group);
|
||||
+
|
||||
+void virCgroupFree(virCgroupPtr *group);
|
||||
+
|
||||
+#endif /* CGROUP_H */
|
118
cgshares.patch
Normal file
118
cgshares.patch
Normal file
@ -0,0 +1,118 @@
|
||||
Add get/set of cpu.shares to cgroup implementation
|
||||
|
||||
This brings get/set of U64 out of the #if 0, which looks messier than it is.
|
||||
|
||||
diff -r d18631472325 src/cgroup.c
|
||||
--- a/src/cgroup.c Tue Oct 07 08:19:56 2008 -0700
|
||||
+++ b/src/cgroup.c Tue Oct 07 08:20:56 2008 -0700
|
||||
@@ -224,26 +224,6 @@
|
||||
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 @@
|
||||
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;
|
||||
|
||||
- if (sscanf(strval, "%" SCNu64, value) != 1)
|
||||
- rc = -EINVAL;
|
||||
-out:
|
||||
+ rc = virCgroupSetValueStr(group, key, strval);
|
||||
+
|
||||
VIR_FREE(strval);
|
||||
|
||||
return rc;
|
||||
@@ -331,6 +312,25 @@
|
||||
return rc;
|
||||
}
|
||||
#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 @@
|
||||
|
||||
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 -r d18631472325 src/cgroup.h
|
||||
--- a/src/cgroup.h Tue Oct 07 08:19:56 2008 -0700
|
||||
+++ b/src/cgroup.h Tue Oct 07 08:20:56 2008 -0700
|
||||
@@ -36,6 +36,9 @@
|
||||
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);
|
@ -1,3 +1,9 @@
|
||||
-------------------------------------------------------------------
|
||||
Fri Oct 10 10:48:19 MDT 2008 - jfehlig@novell.com
|
||||
|
||||
- Added upstream patches providing additional LXC support
|
||||
bnc#433881
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Oct 6 15:36:17 MDT 2008 - jfehlig@novell.com
|
||||
|
||||
|
15
libvirt.spec
15
libvirt.spec
@ -49,7 +49,7 @@ License: LGPL v2.1 or later
|
||||
Group: Development/Libraries/C and C++
|
||||
AutoReqProv: yes
|
||||
Version: 0.4.6
|
||||
Release: 1
|
||||
Release: 2
|
||||
Summary: A C toolkit to interract with the virtualization capabilities of Linux
|
||||
Requires: readline
|
||||
Requires: ncurses
|
||||
@ -72,6 +72,11 @@ Patch2: fs-storage-driver.patch
|
||||
Patch3: snapshots.patch
|
||||
Patch4: vif-parsing.patch
|
||||
Patch5: xen-maxmem.patch
|
||||
Patch6: cgroup.patch
|
||||
Patch7: lxc_res_mem.patch
|
||||
Patch8: cgshares.patch
|
||||
Patch9: lxcsched.patch
|
||||
Patch10: lxcvirsh.patch
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
|
||||
%description
|
||||
@ -168,6 +173,11 @@ Authors:
|
||||
%patch3 -p1
|
||||
%patch4 -p1
|
||||
%patch5 -p1
|
||||
%patch6 -p1
|
||||
%patch7 -p1
|
||||
%patch8 -p1
|
||||
%patch9 -p1
|
||||
%patch10 -p1
|
||||
rm po/no.*
|
||||
|
||||
%build
|
||||
@ -300,6 +310,9 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%{py_sitedir}/libvirtmod*
|
||||
|
||||
%changelog
|
||||
* Fri Oct 10 2008 jfehlig@novell.com
|
||||
- Added upstream patches providing additional LXC support
|
||||
bnc#433881
|
||||
* Mon Oct 06 2008 jfehlig@novell.com
|
||||
- Use xend vs hypercall interface to change max mem setting
|
||||
bnc#431766
|
||||
|
198
lxc_res_mem.patch
Normal file
198
lxc_res_mem.patch
Normal file
@ -0,0 +1,198 @@
|
||||
# HG changeset patch
|
||||
# User danms
|
||||
# Date 1223052361 0
|
||||
# Node ID a28490b116b0430aa0d4f579bba57d52793312ed
|
||||
# Parent 47378698026980b5734c81f9480b50c783dde68a
|
||||
[r2008-10-03 16:46:01 by danms] Add cgroup manipulation and LXC driver
|
||||
|
||||
diff -r 473786980269 -r a28490b116b0 src/Makefile.am
|
||||
--- a/src/Makefile.am Thu Oct 02 15:04:11 2008 +0000
|
||||
+++ b/src/Makefile.am Fri Oct 03 16:46:01 2008 +0000
|
||||
@@ -90,13 +90,15 @@
|
||||
lxc_conf.c lxc_conf.h \
|
||||
lxc_container.c lxc_container.h \
|
||||
lxc_driver.c lxc_driver.h \
|
||||
- veth.c veth.h
|
||||
+ veth.c veth.h \
|
||||
+ cgroup.c cgroup.h
|
||||
|
||||
LXC_CONTROLLER_SOURCES = \
|
||||
lxc_conf.c lxc_conf.h \
|
||||
lxc_container.c lxc_container.h \
|
||||
lxc_controller.c \
|
||||
- veth.c veth.h
|
||||
+ veth.c veth.h \
|
||||
+ cgroup.c cgroup.h
|
||||
|
||||
OPENVZ_DRIVER_SOURCES = \
|
||||
openvz_conf.c openvz_conf.h \
|
||||
diff -r 473786980269 -r a28490b116b0 src/lxc_container.c
|
||||
--- a/src/lxc_container.c Thu Oct 02 15:04:11 2008 +0000
|
||||
+++ b/src/lxc_container.c Fri Oct 03 16:46:01 2008 +0000
|
||||
@@ -320,12 +320,12 @@
|
||||
mode_t mode;
|
||||
const char *path;
|
||||
} devs[] = {
|
||||
- { 1, 3, 0666, "/dev/null" },
|
||||
- { 1, 5, 0666, "/dev/zero" },
|
||||
- { 1, 7, 0666, "/dev/full" },
|
||||
- { 5, 1, 0600, "/dev/console" },
|
||||
- { 1, 8, 0666, "/dev/random" },
|
||||
- { 1, 9, 0666, "/dev/urandom" },
|
||||
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_NULL, 0666, "/dev/null" },
|
||||
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_ZERO, 0666, "/dev/zero" },
|
||||
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_FULL, 0666, "/dev/full" },
|
||||
+ { LXC_DEV_MAJ_TTY, LXC_DEV_MIN_CONSOLE, 0600, "/dev/console" },
|
||||
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_RANDOM, 0666, "/dev/random" },
|
||||
+ { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM, 0666, "/dev/urandom" },
|
||||
};
|
||||
|
||||
if (virFileMakePath("/dev") < 0 ||
|
||||
diff -r 473786980269 -r a28490b116b0 src/lxc_container.h
|
||||
--- a/src/lxc_container.h Thu Oct 02 15:04:11 2008 +0000
|
||||
+++ b/src/lxc_container.h Fri Oct 03 16:46:01 2008 +0000
|
||||
@@ -30,6 +30,16 @@
|
||||
LXC_CONTAINER_FEATURE_NET = (1 << 0),
|
||||
};
|
||||
|
||||
+#define LXC_DEV_MAJ_MEMORY 1
|
||||
+#define LXC_DEV_MIN_NULL 3
|
||||
+#define LXC_DEV_MIN_ZERO 5
|
||||
+#define LXC_DEV_MIN_FULL 7
|
||||
+#define LXC_DEV_MIN_RANDOM 8
|
||||
+#define LXC_DEV_MIN_URANDOM 9
|
||||
+
|
||||
+#define LXC_DEV_MAJ_TTY 5
|
||||
+#define LXC_DEV_MIN_CONSOLE 1
|
||||
+
|
||||
int lxcContainerSendContinue(int control);
|
||||
|
||||
int lxcContainerStart(virDomainDefPtr def,
|
||||
diff -r 473786980269 -r a28490b116b0 src/lxc_controller.c
|
||||
--- a/src/lxc_controller.c Thu Oct 02 15:04:11 2008 +0000
|
||||
+++ b/src/lxc_controller.c Fri Oct 03 16:46:01 2008 +0000
|
||||
@@ -42,12 +42,82 @@
|
||||
#include "veth.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
-
|
||||
+#include "cgroup.h"
|
||||
|
||||
#define DEBUG(fmt,...) VIR_DEBUG(__FILE__, fmt, __VA_ARGS__)
|
||||
#define DEBUG0(msg) VIR_DEBUG(__FILE__, "%s", msg)
|
||||
|
||||
int debugFlag = 0;
|
||||
+
|
||||
+struct cgroup_device_policy {
|
||||
+ char type;
|
||||
+ int major;
|
||||
+ int minor;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * lxcSetContainerResources
|
||||
+ * @def: pointer to virtual machine structure
|
||||
+ *
|
||||
+ * Creates a cgroup for the container, moves the task inside,
|
||||
+ * and sets resource limits
|
||||
+ *
|
||||
+ * Returns 0 on success or -1 in case of error
|
||||
+ */
|
||||
+static int lxcSetContainerResources(virDomainDefPtr def)
|
||||
+{
|
||||
+ virCgroupPtr cgroup;
|
||||
+ int rc = -1;
|
||||
+ int i;
|
||||
+ struct cgroup_device_policy devices[] = {
|
||||
+ {'c', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_NULL},
|
||||
+ {'c', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_ZERO},
|
||||
+ {'c', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_FULL},
|
||||
+ {'c', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_RANDOM},
|
||||
+ {'c', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM},
|
||||
+ {'c', LXC_DEV_MAJ_TTY, LXC_DEV_MIN_CONSOLE},
|
||||
+ {0, 0, 0}};
|
||||
+
|
||||
+ if (virCgroupHaveSupport() != 0)
|
||||
+ return 0; /* Not supported, so claim success */
|
||||
+
|
||||
+ rc = virCgroupForDomain(def, "lxc", &cgroup);
|
||||
+ if (rc != 0) {
|
||||
+ lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("Unable to create cgroup for %s\n"), def->name);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ rc = virCgroupSetMemory(cgroup, def->maxmem);
|
||||
+ if (rc != 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ rc = virCgroupDenyAllDevices(cgroup);
|
||||
+ if (rc != 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ for (i = 0; devices[i].type != 0; i++) {
|
||||
+ struct cgroup_device_policy *dev = &devices[i];
|
||||
+ rc = virCgroupAllowDevice(cgroup,
|
||||
+ dev->type,
|
||||
+ dev->major,
|
||||
+ dev->minor);
|
||||
+ if (rc != 0)
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ rc = virCgroupAddTask(cgroup, getpid());
|
||||
+out:
|
||||
+ if (rc != 0) {
|
||||
+ lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("Failed to set lxc resources: %s\n"), strerror(-rc));
|
||||
+ virCgroupRemove(cgroup);
|
||||
+ }
|
||||
+
|
||||
+ virCgroupFree(&cgroup);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
|
||||
static char*lxcMonitorPath(virDomainDefPtr def)
|
||||
{
|
||||
@@ -394,6 +464,9 @@
|
||||
if (lxcControllerMoveInterfaces(nveths, veths, container) < 0)
|
||||
goto cleanup;
|
||||
|
||||
+ if (lxcSetContainerResources(def) < 0)
|
||||
+ goto cleanup;
|
||||
+
|
||||
if (lxcContainerSendContinue(control[0]) < 0)
|
||||
goto cleanup;
|
||||
|
||||
diff -r 473786980269 -r a28490b116b0 src/lxc_driver.c
|
||||
--- a/src/lxc_driver.c Thu Oct 02 15:04:11 2008 +0000
|
||||
+++ b/src/lxc_driver.c Fri Oct 03 16:46:01 2008 +0000
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "bridge.h"
|
||||
#include "veth.h"
|
||||
#include "event.h"
|
||||
+#include "cgroup.h"
|
||||
|
||||
|
||||
/* debug macros */
|
||||
@@ -376,6 +377,7 @@
|
||||
int waitRc;
|
||||
int childStatus = -1;
|
||||
virDomainNetDefPtr net;
|
||||
+ virCgroupPtr cgroup;
|
||||
|
||||
while (((waitRc = waitpid(vm->pid, &childStatus, 0)) == -1) &&
|
||||
errno == EINTR)
|
||||
@@ -408,6 +410,11 @@
|
||||
for (net = vm->def->nets; net; net = net->next) {
|
||||
vethInterfaceUpOrDown(net->ifname, 0);
|
||||
vethDelete(net->ifname);
|
||||
+ }
|
||||
+
|
||||
+ if (virCgroupForDomain(vm->def, "lxc", &cgroup) == 0) {
|
||||
+ virCgroupRemove(cgroup);
|
||||
+ virCgroupFree(&cgroup);
|
||||
}
|
||||
|
||||
return rc;
|
130
lxcsched.patch
Normal file
130
lxcsched.patch
Normal file
@ -0,0 +1,130 @@
|
||||
Add scheduling parameter support for LXC domains
|
||||
|
||||
Index: libvirt-0.4.6/src/lxc_driver.c
|
||||
===================================================================
|
||||
--- libvirt-0.4.6.orig/src/lxc_driver.c
|
||||
+++ libvirt-0.4.6/src/lxc_driver.c
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <unistd.h>
|
||||
#include <wait.h>
|
||||
|
||||
+#include "internal.h"
|
||||
#include "lxc_conf.h"
|
||||
#include "lxc_container.h"
|
||||
#include "lxc_driver.h"
|
||||
@@ -1149,6 +1150,94 @@ static int lxcVersion(virConnectPtr conn
|
||||
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 */
|
||||
@@ -1198,9 +1287,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 */
|
||||
@@ -1217,7 +1306,6 @@ static virDriver lxcDriver = {
|
||||
NULL, /* domainListSnapshots */
|
||||
};
|
||||
|
||||
-
|
||||
static virStateDriver lxcStateDriver = {
|
||||
lxcStartup,
|
||||
lxcShutdown,
|
123
lxcvirsh.patch
Normal file
123
lxcvirsh.patch
Normal file
@ -0,0 +1,123 @@
|
||||
Add generic parameter=value support for virsh's schedinfo command
|
||||
|
||||
This patch maintains the two Xen-specific --weight and --cap options,
|
||||
but adds support for setting arbitrary parameters by specifying them in
|
||||
param=value syntax.
|
||||
|
||||
Changes to the virsh manual are included.
|
||||
|
||||
Changes:
|
||||
- Replace use of 'a' conversion modifier with pre-alloc
|
||||
|
||||
Index: libvirt-0.4.6/docs/virsh.pod
|
||||
===================================================================
|
||||
--- libvirt-0.4.6.orig/docs/virsh.pod
|
||||
+++ libvirt-0.4.6/docs/virsh.pod
|
||||
@@ -322,12 +322,14 @@ This is roughly equivalent to doing a hi
|
||||
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>
|
||||
|
||||
Index: libvirt-0.4.6/src/virsh.c
|
||||
===================================================================
|
||||
--- libvirt-0.4.6.orig/src/virsh.c
|
||||
+++ libvirt-0.4.6/src/virsh.c
|
||||
@@ -1295,6 +1295,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}
|
||||
@@ -1304,6 +1305,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;
|
||||
@@ -1311,6 +1315,7 @@ cmdSchedinfo(vshControl *ctl, const vshC
|
||||
int nr_inputparams = 0;
|
||||
int inputparams = 0;
|
||||
int weightfound = 0;
|
||||
+ int setfound = 0;
|
||||
int weight = 0;
|
||||
int capfound = 0;
|
||||
int cap = 0;
|
||||
@@ -1324,7 +1329,7 @@ cmdSchedinfo(vshControl *ctl, const vshC
|
||||
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) {
|
||||
@@ -1345,6 +1350,25 @@ cmdSchedinfo(vshControl *ctl, const vshC
|
||||
}
|
||||
}
|
||||
|
||||
+ 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;
|
||||
@@ -1363,7 +1387,14 @@ cmdSchedinfo(vshControl *ctl, const vshC
|
||||
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);
|
||||
|
||||
@@ -1430,6 +1461,7 @@ cmdSchedinfo(vshControl *ctl, const vshC
|
||||
}
|
||||
cleanup:
|
||||
free(params);
|
||||
+ free(param_name);
|
||||
virDomainFree(dom);
|
||||
return ret_val;
|
||||
}
|
Loading…
Reference in New Issue
Block a user