From: "Daniel P. Berrange" <berrange(a)redhat.com>
The introduction of /sys/fs/cgroup came in fairly recent kernels.
Prior to that time distros would pick a custom directory like
/cgroup or /dev/cgroup. We need to auto-detect where this is,
rather than hardcoding it
---
src/lxc/lxc_container.c | 71 +++++++++++++++++++++++++++++++++----------------
src/util/cgroup.h | 2 --
2 files changed, 48 insertions(+), 25 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index f3a4622..9bc5610 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -1307,7 +1307,8 @@ static void lxcContainerCGroupFree(struct lxcContainerCGroup
*mounts,
static int lxcContainerIdentifyCGroups(struct lxcContainerCGroup **mountsret,
- size_t *nmountsret)
+ size_t *nmountsret,
+ char **root)
{
FILE *procmnt = NULL;
struct mntent mntent;
@@ -1321,8 +1322,9 @@ static int lxcContainerIdentifyCGroups(struct lxcContainerCGroup
**mountsret,
*mountsret = NULL;
*nmountsret = 0;
+ *root = NULL;
- VIR_DEBUG("Finding cgroups mount points under %s",
VIR_CGROUP_SYSFS_MOUNT);
+ VIR_DEBUG("Finding cgroups mount points of type cgroup");
if (!(procmnt = setmntent("/proc/mounts", "r"))) {
virReportSystemError(errno, "%s",
@@ -1332,10 +1334,24 @@ static int lxcContainerIdentifyCGroups(struct lxcContainerCGroup
**mountsret,
while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) {
VIR_DEBUG("Got %s", mntent.mnt_dir);
- if (STRNEQ(mntent.mnt_type, "cgroup") ||
- !STRPREFIX(mntent.mnt_dir, VIR_CGROUP_SYSFS_MOUNT))
+ if (STRNEQ(mntent.mnt_type, "cgroup"))
continue;
+ if (!*root) {
+ char *tmp;
+ if (!(*root = strdup(mntent.mnt_dir))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ tmp = strrchr(*root, '/');
+ *tmp = '\0';
+ } else if (!STRPREFIX(mntent.mnt_dir, *root)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Cgroup %s is not mounted under %s"),
+ mntent.mnt_dir, *root);
+ goto cleanup;
+ }
+
/* Skip named mounts with no controller since they're
* for application use only ie systemd */
if (strstr(mntent.mnt_opts, "name="))
@@ -1349,14 +1365,14 @@ static int lxcContainerIdentifyCGroups(struct lxcContainerCGroup
**mountsret,
virReportOOMError();
goto cleanup;
}
- VIR_DEBUG("Grabbed %s", mntent.mnt_dir);
+ VIR_DEBUG("Grabbed '%s'", mntent.mnt_dir);
}
- VIR_DEBUG("Checking for symlinks in %s", VIR_CGROUP_SYSFS_MOUNT);
- if (!(dh = opendir(VIR_CGROUP_SYSFS_MOUNT))) {
+ VIR_DEBUG("Checking for symlinks in %s", *root);
+ if (!(dh = opendir(*root))) {
virReportSystemError(errno,
_("Unable to read directory %s"),
- VIR_CGROUP_SYSFS_MOUNT);
+ *root);
goto cleanup;
}
@@ -1370,7 +1386,7 @@ static int lxcContainerIdentifyCGroups(struct lxcContainerCGroup
**mountsret,
continue;
VIR_DEBUG("Checking entry %s", dent->d_name);
- if (virAsprintf(&path, "%s/%s", VIR_CGROUP_SYSFS_MOUNT,
dent->d_name) < 0) {
+ if (virAsprintf(&path, "%s/%s", *root, dent->d_name) < 0) {
virReportOOMError();
goto cleanup;
}
@@ -1410,25 +1426,28 @@ cleanup:
endmntent(procmnt);
VIR_FREE(path);
- if (ret < 0)
+ if (ret < 0) {
lxcContainerCGroupFree(mounts, nmounts);
+ VIR_FREE(*root);
+ }
return ret;
}
static int lxcContainerMountCGroups(struct lxcContainerCGroup *mounts,
size_t nmounts,
- char * sec_mount_options)
+ const char *root,
+ char *sec_mount_options)
{
size_t i;
char *opts = NULL;
- VIR_DEBUG("Mounting cgroups at '%s'", VIR_CGROUP_SYSFS_MOUNT);
+ VIR_DEBUG("Mounting cgroups at '%s'", root);
- if (virFileMakePath(VIR_CGROUP_SYSFS_MOUNT) < 0) {
+ if (virFileMakePath(root) < 0) {
virReportSystemError(errno,
_("Unable to create directory %s"),
- VIR_CGROUP_SYSFS_MOUNT);
+ root);
return -1;
}
@@ -1438,11 +1457,11 @@ static int lxcContainerMountCGroups(struct lxcContainerCGroup
*mounts,
return -1;
}
- if (mount("tmpfs", VIR_CGROUP_SYSFS_MOUNT, "tmpfs",
MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
+ if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC,
opts) < 0) {
VIR_FREE(opts);
virReportSystemError(errno,
_("Failed to mount %s on %s type %s"),
- "tmpfs", VIR_CGROUP_SYSFS_MOUNT,
"tmpfs");
+ "tmpfs", root, "tmpfs");
return -1;
}
VIR_FREE(opts);
@@ -1467,10 +1486,10 @@ static int lxcContainerMountCGroups(struct lxcContainerCGroup
*mounts,
}
if (mount("cgroup", mounts[i].dir, "cgroup",
- 0, mounts[i].dir + strlen(VIR_CGROUP_SYSFS_MOUNT) + 1) < 0) {
+ 0, mounts[i].dir + strlen(root) + 1) < 0) {
virReportSystemError(errno,
- _("Failed to mount %s on %s"),
- "cgroup", mounts[i].dir);
+ _("Failed to mount cgroup on
'%s'"),
+ mounts[i].dir);
return -1;
}
}
@@ -1493,10 +1512,11 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
struct lxcContainerCGroup *mounts = NULL;
size_t nmounts = 0;
int ret = -1;
+ char *cgroupRoot;
/* Before pivoting we need to identify any
* cgroups controllers that are mounted */
- if (lxcContainerIdentifyCGroups(&mounts, &nmounts) < 0)
+ if (lxcContainerIdentifyCGroups(&mounts, &nmounts, &cgroupRoot) < 0)
return -1;
/* Gives us a private root, leaving all parent OS mounts on /.oldroot */
@@ -1519,7 +1539,8 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
/* Now we can re-mount the cgroups controllers in the
* same configuration as before */
- if (lxcContainerMountCGroups(mounts, nmounts, sec_mount_options) < 0)
+ if (lxcContainerMountCGroups(mounts, nmounts,
+ cgroupRoot, sec_mount_options) < 0)
goto cleanup;
/* Mounts /dev/pts */
@@ -1542,6 +1563,7 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
cleanup:
lxcContainerCGroupFree(mounts, nmounts);
+ VIR_FREE(cgroupRoot);
return ret;
}
@@ -1555,6 +1577,7 @@ static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef,
int ret = -1;
struct lxcContainerCGroup *mounts = NULL;
size_t nmounts = 0;
+ char *cgroupRoot;
VIR_DEBUG("def=%p", vmDef);
/*
@@ -1582,7 +1605,7 @@ static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef,
/* Before replacing /sys we need to identify any
* cgroups controllers that are mounted */
- if (lxcContainerIdentifyCGroups(&mounts, &nmounts) < 0)
+ if (lxcContainerIdentifyCGroups(&mounts, &nmounts, &cgroupRoot) < 0)
return -1;
/* Gets rid of any existing stuff under /proc, since we need new
@@ -1598,7 +1621,8 @@ static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef,
/* Now we can re-mount the cgroups controllers in the
* same configuration as before */
- if (lxcContainerMountCGroups(mounts, nmounts, sec_mount_options) < 0)
+ if (lxcContainerMountCGroups(mounts, nmounts,
+ cgroupRoot, sec_mount_options) < 0)
goto cleanup;
VIR_DEBUG("Mounting completed");
@@ -1607,6 +1631,7 @@ static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef,
cleanup:
lxcContainerCGroupFree(mounts, nmounts);
+ VIR_FREE(cgroupRoot);
return ret;
}
diff --git a/src/util/cgroup.h b/src/util/cgroup.h
index 68ac232..bb12b40 100644
--- a/src/util/cgroup.h
+++ b/src/util/cgroup.h
@@ -28,8 +28,6 @@
struct virCgroup;
typedef struct virCgroup *virCgroupPtr;
-# define VIR_CGROUP_SYSFS_MOUNT "/sys/fs/cgroup"
-
enum {
VIR_CGROUP_CONTROLLER_CPU,
VIR_CGROUP_CONTROLLER_CPUACCT,
--
1.7.11.2