SHA256
1
0
forked from pool/libvirt
OBS User unknown 2008-10-13 15:08:24 +00:00 committed by Git OBS Bridge
parent d045108cb4
commit 92cce1a7b8
7 changed files with 1411 additions and 1 deletions

822
cgroup.patch Normal file
View 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
View 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);

View File

@ -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

View File

@ -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
View 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
View 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 = &params[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 *)&params[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
View 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, &param_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;
}