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.
*
}
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++;
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++;
*/
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) {
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;
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;
* 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,
}
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);
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);
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;
}
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)) {
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;
* 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");
}
* 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;
* 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 */
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;
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;
};