[libvirt] [PATCH] Don't assume use of /sys/fs/cgroup

Daniel P. Berrange berrange at redhat.com
Thu Sep 6 14:23:38 UTC 2012


From: "Daniel P. Berrange" <berrange at 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




More information about the libvir-list mailing list