]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
Fixed libcgroup to be aware of hierarchies mounted multiple times.
authorJan Safranek <jsafrane@redhat.com>
Wed, 6 Apr 2011 06:37:04 +0000 (08:37 +0200)
committerJan Safranek <jsafrane@redhat.com>
Mon, 18 Apr 2011 12:13:37 +0000 (14:13 +0200)
Current libcgroup design handles each hierarchy only once. If a hierarchy
is mounted twice or more times, only the first mount point is taken into
account and the others are 'invisible' to libcgroup.

This causes cgsnapshot and lssubsys to show only one mount point for a
hierarchy and especially in case of cgsnapshot it's not what user expects.
The patch below adds a list of all mount points to cg_mount_table_s structure.

Signed-off-by: Jan Safranek <jsafrane@redhat.com>
Acked-by: Ivana Hutarova Varekova<varekova@redhat.com>
src/api.c
src/config.c
src/libcgroup-internal.h

index c3dba988a06d6574b3345abb2774ca38f54e61ad..0dc135ab1dda5c1f47bbc780f9143e7ee2fbc762 100644 (file)
--- a/src/api.c
+++ b/src/api.c
@@ -718,6 +718,29 @@ unlock:
        return ret;
 }
 
+int cg_add_duplicate_mount(struct cg_mount_table_s *item, const char *path)
+{
+       struct cg_mount_point *mount, *it;
+
+       mount = malloc(sizeof(struct cg_mount_point));
+       if (!mount)
+               return ECGFAIL;
+       mount->next = NULL;
+       strncpy(mount->path, path, sizeof(mount->path));
+       mount->path[sizeof(mount->path)-1] = '\0';
+
+       /*
+        * Add the mount point to the end of the list.
+        * Assuming the list is short, no optimization is done.
+        */
+       it = &item->mount;
+       while (it->next)
+               it = it->next;
+
+       it->next = mount;
+       return 0;
+}
+
 /**
  * cgroup_init(), initializes the MOUNT_POINT.
  *
@@ -826,12 +849,19 @@ int cgroup_init(void)
                        }
                        if (duplicate) {
                                cgroup_dbg("controller %s is already mounted on %s\n",
-                                       mntopt, cg_mount_table[j].path);
-                               break;
+                                       mntopt, cg_mount_table[j].mount.path);
+                               ret = cg_add_duplicate_mount(&cg_mount_table[j],
+                                               ent->mnt_dir);
+                               if (ret)
+                                       goto unlock_exit;
+                               /* continue with next controller */
+                               continue;
                        }
 
                        strcpy(cg_mount_table[found_mnt].name, controllers[i]);
-                       strcpy(cg_mount_table[found_mnt].path, ent->mnt_dir);
+                       strcpy(cg_mount_table[found_mnt].mount.path,
+                                       ent->mnt_dir);
+                       cg_mount_table[found_mnt].mount.next = NULL;
                        cgroup_dbg("Found cgroup option %s, count %d\n",
                                ent->mnt_opts, found_mnt);
                        found_mnt++;
@@ -859,12 +889,18 @@ int cgroup_init(void)
 
                        if (duplicate) {
                                cgroup_dbg("controller %s is already mounted on %s\n",
-                                       mntopt, cg_mount_table[j].path);
+                                       mntopt, cg_mount_table[j].mount.path);
+                               ret = cg_add_duplicate_mount(&cg_mount_table[j],
+                                               ent->mnt_dir);
+                               if (ret)
+                                       goto unlock_exit;
                                continue;
                        }
 
                        strcpy(cg_mount_table[found_mnt].name, mntopt);
-                       strcpy(cg_mount_table[found_mnt].path, ent->mnt_dir);
+                       strcpy(cg_mount_table[found_mnt].mount.path,
+                                       ent->mnt_dir);
+                       cg_mount_table[found_mnt].mount.next = NULL;
                        cgroup_dbg("Found cgroup option %s, count %d\n",
                                ent->mnt_opts, found_mnt);
                        found_mnt++;
@@ -959,10 +995,12 @@ static char *cg_build_path_locked(const char *name, char *path,
                 */
                if (strcmp(cg_mount_table[i].name, type) == 0) {
                        if (cg_namespace_table[i]) {
-                               sprintf(path, "%s/%s/", cg_mount_table[i].path,
-                                                       cg_namespace_table[i]);
+                               sprintf(path, "%s/%s/",
+                                               cg_mount_table[i].mount.path,
+                                               cg_namespace_table[i]);
                        } else {
-                               sprintf(path, "%s/", cg_mount_table[i].path);
+                               sprintf(path, "%s/",
+                                               cg_mount_table[i].mount.path);
                        }
 
                        if (name) {
@@ -3282,7 +3320,7 @@ int cgroup_get_controller_next(void **handle, struct cgroup_mount_point *info)
 
        strncpy(info->name, cg_mount_table[*pos].name, FILENAME_MAX);
 
-       strncpy(info->path, cg_mount_table[*pos].path, FILENAME_MAX);
+       strncpy(info->path, cg_mount_table[*pos].mount.path, FILENAME_MAX);
 
        (*pos)++;
        *handle = pos;
@@ -3608,7 +3646,7 @@ int cgroup_get_subsys_mount_point(const char *controller, char **mount_point)
                if (strncmp(cg_mount_table[i].name, controller, FILENAME_MAX))
                        continue;
 
-               *mount_point = strdup(cg_mount_table[i].path);
+               *mount_point = strdup(cg_mount_table[i].mount.path);
 
                if (!*mount_point) {
                        last_errno = errno;
index 0f71003f3755f59750d214b079e986191d3b2f1d..63c5946baef18ce17a38eb03c053738d736e2f0b 100644 (file)
@@ -328,7 +328,8 @@ int cgroup_config_insert_into_mount_table(char *name, char *mount_point)
         * Merge controller names with the same mount point
         */
        for (i = 0; i < config_table_index; i++) {
-               if (strcmp(config_mount_table[i].path, mount_point) == 0) {
+               if (strcmp(config_mount_table[i].mount.path,
+                               mount_point) == 0) {
                        char *cname = config_mount_table[i].name;
                        strncat(cname, ",", FILENAME_MAX - strlen(cname) - 1);
                        strncat(cname, name,
@@ -338,7 +339,8 @@ int cgroup_config_insert_into_mount_table(char *name, char *mount_point)
        }
 
        strcpy(config_mount_table[config_table_index].name, name);
-       strcpy(config_mount_table[config_table_index].path, mount_point);
+       strcpy(config_mount_table[config_table_index].mount.path, mount_point);
+       config_mount_table[config_table_index].mount.next = NULL;
        config_table_index++;
 done:
        pthread_rwlock_unlock(&config_table_lock);
@@ -368,7 +370,9 @@ int cgroup_config_insert_into_namespace_table(char *name, char *nspath)
        pthread_rwlock_wrlock(&namespace_table_lock);
 
        strcpy(config_namespace_table[namespace_table_index].name, name);
-       strcpy(config_namespace_table[namespace_table_index].path, nspath);
+       strcpy(config_namespace_table[namespace_table_index].mount.path,
+                       nspath);
+       config_namespace_table[namespace_table_index].mount.next = NULL;
        namespace_table_index++;
 
        pthread_rwlock_unlock(&namespace_table_lock);
@@ -398,7 +402,7 @@ static int cgroup_config_mount_fs(void)
        for (i = 0; i < config_table_index; i++) {
                struct cg_mount_table_s *curr = &(config_mount_table[i]);
 
-               ret = stat(curr->path, &buff);
+               ret = stat(curr->mount.path, &buff);
 
                if (ret < 0 && errno != ENOENT) {
                        last_errno = errno;
@@ -406,7 +410,7 @@ static int cgroup_config_mount_fs(void)
                }
 
                if (errno == ENOENT) {
-                       ret = cg_mkdir_p(curr->path);
+                       ret = cg_mkdir_p(curr->mount.path);
                        if (ret)
                                return ret;
                } else if (!S_ISDIR(buff.st_mode)) {
@@ -415,8 +419,8 @@ static int cgroup_config_mount_fs(void)
                        return ECGOTHER;
                }
 
-               ret = mount(CGROUP_FILESYSTEM, curr->path, CGROUP_FILESYSTEM,
-                                                               0, curr->name);
+               ret = mount(CGROUP_FILESYSTEM, curr->mount.path,
+                               CGROUP_FILESYSTEM, 0, curr->name);
 
                if (ret < 0)
                        return ECGMOUNTFAIL;
@@ -477,10 +481,10 @@ static int cgroup_config_unmount_controllers(void)
                 * We ignore failures and ensure that all mounted
                 * containers are unmounted
                 */
-               error = umount(config_mount_table[i].path);
+               error = umount(config_mount_table[i].mount.path);
                if (error < 0)
                        cgroup_dbg("Unmount failed\n");
-               error = rmdir(config_mount_table[i].path);
+               error = rmdir(config_mount_table[i].mount.path);
                if (error < 0)
                        cgroup_dbg("rmdir failed\n");
        }
@@ -503,7 +507,7 @@ static int config_validate_namespaces(void)
                 * are good, else we will need to go for two
                 * loops. This should be optimized in the future
                 */
-               mount_path = cg_mount_table[i].path;
+               mount_path = cg_mount_table[i].mount.path;
 
                if (!mount_path) {
                        last_errno = errno;
@@ -538,7 +542,7 @@ static int config_validate_namespaces(void)
                 * Search through the mount table to locate which subsystems
                 * are mounted together.
                 */
-               while (!strncmp(cg_mount_table[j].path, mount_path,
+               while (!strncmp(cg_mount_table[j].mount.path, mount_path,
                                                        FILENAME_MAX)) {
                        if (!namespace && cg_namespace_table[j]) {
                                /* In case namespace is not setup, set it up */
@@ -636,7 +640,8 @@ static int config_order_namespace_table(void)
                                        goto error_out;
                                }
 
-                               cg_namespace_table[j] = strdup(config_namespace_table[i].path);
+                               cg_namespace_table[j] = strdup(
+                                       config_namespace_table[i].mount.path);
                                if (!cg_namespace_table[j]) {
                                        last_errno = errno;
                                        error = ECGOTHER;
index 801b35e452abaf72274110a0906039aa4d4d31ce..45c1dede668656f0eee4954c12b40499aae8f0c1 100644 (file)
@@ -88,10 +88,18 @@ struct cgroup {
        gid_t control_gid;
 };
 
+struct cg_mount_point {
+       char path[FILENAME_MAX];
+       struct cg_mount_point *next;
+};
 
 struct cg_mount_table_s {
+       /** Controller name. */
        char name[FILENAME_MAX];
-       char path[FILENAME_MAX];
+       /**
+        * List of mount points, at least one mount point is there for sure.
+        */
+       struct cg_mount_point mount;
        int index;
 };