Don't assume use of /sys/fs/cgroup

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

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2012-09-06 15:19:32 +01:00
parent 48d112210d
commit a4fd740561
2 changed files with 48 additions and 25 deletions

View File

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

View File

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