From: "Daniel P. Berrange" <berrange(a)redhat.com>
The LXC driver currently has code to detect cgroups mounts
and then re-mount them inside the new root filesystem. Replace
this fragile code with a call to virCgroupIsolateMount.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/lxc/lxc_container.c | 237 ++----------------------------------------------
1 file changed, 8 insertions(+), 229 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index ab27a92..b0367e4 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -1735,227 +1735,6 @@ static int lxcContainerSetupAllHostdevs(virDomainDefPtr vmDef,
}
-struct lxcContainerCGroup {
- const char *dir;
- const char *linkDest;
-};
-
-
-static void lxcContainerCGroupFree(struct lxcContainerCGroup *mounts,
- size_t nmounts)
-{
- size_t i;
-
- if (!mounts)
- return;
-
- for (i = 0 ; i < nmounts ; i++) {
- VIR_FREE(mounts[i].dir);
- VIR_FREE(mounts[i].linkDest);
- }
- VIR_FREE(mounts);
-}
-
-
-static int lxcContainerIdentifyCGroups(struct lxcContainerCGroup **mountsret,
- size_t *nmountsret,
- char **root)
-{
- FILE *procmnt = NULL;
- struct mntent mntent;
- struct dirent *dent;
- char mntbuf[1024];
- int ret = -1;
- struct lxcContainerCGroup *mounts = NULL;
- size_t nmounts = 0;
- DIR *dh = NULL;
- char *path = NULL;
-
- *mountsret = NULL;
- *nmountsret = 0;
- *root = NULL;
-
- VIR_DEBUG("Finding cgroups mount points of type cgroup");
-
- if (!(procmnt = setmntent("/proc/mounts", "r"))) {
- virReportSystemError(errno, "%s",
- _("Failed to read /proc/mounts"));
- return -1;
- }
-
- while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) {
- VIR_DEBUG("Got %s", mntent.mnt_dir);
- 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="))
- continue;
-
- if (VIR_EXPAND_N(mounts, nmounts, 1) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- if (!(mounts[nmounts-1].dir = strdup(mntent.mnt_dir))) {
- virReportOOMError();
- goto cleanup;
- }
- VIR_DEBUG("Grabbed '%s'", mntent.mnt_dir);
- }
-
- if (!*root) {
- VIR_DEBUG("No mounted cgroups found");
- ret = 0;
- goto cleanup;
- }
-
- VIR_DEBUG("Checking for symlinks in %s", *root);
- if (!(dh = opendir(*root))) {
- virReportSystemError(errno,
- _("Unable to read directory %s"),
- *root);
- goto cleanup;
- }
-
- while ((dent = readdir(dh)) != NULL) {
- ssize_t rv;
- /* The cgroups links are just relative to the local
- * dir so we don't need a large buf */
- char linkbuf[100];
-
- if (dent->d_name[0] == '.')
- continue;
-
- VIR_DEBUG("Checking entry %s", dent->d_name);
- if (virAsprintf(&path, "%s/%s", *root, dent->d_name) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- if ((rv = readlink(path, linkbuf, sizeof(linkbuf)-1)) < 0) {
- if (errno != EINVAL) {
- virReportSystemError(errno,
- _("Unable to resolve link %s"),
- path);
- VIR_FREE(path);
- goto cleanup;
- }
- /* Ok not a link */
- VIR_FREE(path);
- } else {
- linkbuf[rv] = '\0';
- VIR_DEBUG("Got a link %s to %s", path, linkbuf);
- if (VIR_EXPAND_N(mounts, nmounts, 1) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- if (!(mounts[nmounts-1].linkDest = strdup(linkbuf))) {
- virReportOOMError();
- goto cleanup;
- }
- mounts[nmounts-1].dir = path;
- path = NULL;
- }
- }
-
- *mountsret = mounts;
- *nmountsret = nmounts;
- ret = 0;
-
-cleanup:
- closedir(dh);
- endmntent(procmnt);
- VIR_FREE(path);
-
- if (ret < 0) {
- lxcContainerCGroupFree(mounts, nmounts);
- VIR_FREE(*root);
- }
- return ret;
-}
-
-
-static int lxcContainerMountCGroups(struct lxcContainerCGroup *mounts,
- size_t nmounts,
- const char *root,
- char *sec_mount_options)
-{
- size_t i;
- char *opts = NULL;
-
- VIR_DEBUG("Mounting cgroups at '%s'", root);
-
- if (virFileMakePath(root) < 0) {
- virReportSystemError(errno,
- _("Unable to create directory %s"),
- root);
- return -1;
- }
-
- if (virAsprintf(&opts,
- "mode=755,size=65536%s", sec_mount_options) < 0) {
- virReportOOMError();
- return -1;
- }
-
- 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", root, "tmpfs");
- return -1;
- }
- VIR_FREE(opts);
-
- for (i = 0 ; i < nmounts ; i++) {
- if (mounts[i].linkDest) {
- VIR_DEBUG("Link mount point '%s' to '%s'",
- mounts[i].dir, mounts[i].linkDest);
- if (symlink(mounts[i].linkDest, mounts[i].dir) < 0) {
- virReportSystemError(errno,
- _("Unable to symlink directory %s to
%s"),
- mounts[i].dir, mounts[i].linkDest);
- return -1;
- }
- } else {
- VIR_DEBUG("Create mount point '%s'", mounts[i].dir);
- if (virFileMakePath(mounts[i].dir) < 0) {
- virReportSystemError(errno,
- _("Unable to create directory %s"),
- mounts[i].dir);
- return -1;
- }
-
- if (mount("cgroup", mounts[i].dir, "cgroup",
- 0, mounts[i].dir + strlen(root) + 1) < 0) {
- virReportSystemError(errno,
- _("Failed to mount cgroup on
'%s'"),
- mounts[i].dir);
- return -1;
- }
- }
- }
-
- return 0;
-}
-
-
/* Got a FS mapped to /, we're going the pivot_root
* approach to do a better-chroot-than-chroot
* this is based on this thread
http://lkml.org/lkml/2008/3/5/29
@@ -1966,10 +1745,9 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
size_t nttyPaths,
virSecurityManagerPtr securityDriver)
{
- struct lxcContainerCGroup *mounts = NULL;
- size_t nmounts = 0;
+ virCgroupPtr cgroup = NULL;
+ int rc;
int ret = -1;
- char *cgroupRoot = NULL;
char *sec_mount_options;
if (!(sec_mount_options = virSecurityManagerGetMountOptions(securityDriver, vmDef)))
@@ -1977,8 +1755,11 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
/* Before pivoting we need to identify any
* cgroups controllers that are mounted */
- if (lxcContainerIdentifyCGroups(&mounts, &nmounts, &cgroupRoot) < 0)
+ if ((rc = virCgroupNewSelf(&cgroup)) != 0) {
+ virReportSystemError(-rc, "%s",
+ _("Cannot identify cgroup placement"));
goto cleanup;
+ }
/* Ensure the root filesystem is mounted */
if (lxcContainerPrepareRoot(vmDef, root) < 0)
@@ -2017,8 +1798,7 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
/* Now we can re-mount the cgroups controllers in the
* same configuration as before */
- if (lxcContainerMountCGroups(mounts, nmounts,
- cgroupRoot, sec_mount_options) < 0)
+ if (virCgroupIsolateMount(cgroup, "/.oldroot/", sec_mount_options) < 0)
goto cleanup;
/* Mounts /dev/pts */
@@ -2048,8 +1828,7 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
ret = 0;
cleanup:
- lxcContainerCGroupFree(mounts, nmounts);
- VIR_FREE(cgroupRoot);
+ virCgroupFree(&cgroup);
VIR_FREE(sec_mount_options);
return ret;
}
--
1.8.1.4