]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
Configuration rewrite to use the main cgroups API and several bug fixes
authorBalbir Singh <balbir@linux.vnet.ibm.com>
Mon, 29 Sep 2008 12:26:50 +0000 (12:26 +0000)
committerBalbir Singh <balbir@linux.vnet.ibm.com>
Mon, 29 Sep 2008 12:26:50 +0000 (12:26 +0000)
and configuration enhancements. Primarliy Initiated by Dhaval Giani

Please see svn log of all branches/balbir-config-cleanup

Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>
git-svn-id: https://libcg.svn.sourceforge.net/svnroot/libcg/trunk@201 4f4bb910-9a46-0410-90c8-c897d4f1cd53

Makefile
Makefile.in
api.c
cgconfig.c [new file with mode: 0644]
config.c
file-ops.c [deleted file]
libcgroup-internal.h
libcgroup.h
parse.y
samples/wlm.conf.3

index 380dde752cbe089fa9d1476dccca11c81bdb1a0a..c92d48f437b12796d70746d40d9cc5cc1da80057 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -31,9 +31,8 @@ VERSION=1
 
 all: libcgroup.so cgconfigparser cgexec cgclassify cgrulesengd
 
-cgconfigparser: libcgroup.so config.c y.tab.c lex.yy.c libcgroup.h file-ops.c
-       $(CC) $(CFLAGS) -o $@ y.tab.c lex.yy.c config.c file-ops.c \
-               $(LDFLAGS) $(LIBS)
+cgconfigparser: libcgroup.so cgconfig.c libcgroup.h
+       $(CC) $(CFLAGS) -Wall -o $@ cgconfig.c $(LDFLAGS) $(LIBS)
 
 cgexec: libcgroup.so cgexec.c libcgroup.h
        $(CC) $(CFLAGS) -Wall -o $@ cgexec.c $(LDFLAGS) $(LIBS)
@@ -51,9 +50,9 @@ y.tab.c: parse.y lex.yy.c
 lex.yy.c: lex.l
        $(LEX) lex.l
 
-libcgroup.so: api.c libcgroup.h wrapper.c
+libcgroup.so: api.c libcgroup.h wrapper.c config.c lex.yy.c y.tab.c
        $(CC) $(CFLAGS) -shared -fPIC -Wl,--soname,$@.$(VERSION) -o $@ api.c \
-               wrapper.c
+       wrapper.c lex.yy.c y.tab.c config.c
        ln -sf $@ $@.$(VERSION)
 
 test:
index aa68f4eae93b8e9f90bec26c98a022f62f64cc49..74601cce7c9a8154be282973b4d11a5c930f9318 100644 (file)
@@ -31,9 +31,8 @@ VERSION=1
 
 all: libcgroup.so cgconfigparser cgexec cgclassify cgrulesengd
 
-cgconfigparser: libcgroup.so config.c y.tab.c lex.yy.c libcgroup.h file-ops.c
-       $(CC) $(CFLAGS) -o $@ y.tab.c lex.yy.c config.c file-ops.c \
-               $(LDFLAGS) $(LIBS)
+cgconfigparser: libcgroup.so cgconfig.c libcgroup.h
+       $(CC) $(CFLAGS) -Wall -o $@ cgconfig.c $(LDFLAGS) $(LIBS)
 
 cgexec: libcgroup.so cgexec.c libcgroup.h
        $(CC) $(CFLAGS) -Wall -o $@ cgexec.c $(LDFLAGS) $(LIBS)
@@ -51,9 +50,9 @@ y.tab.c: parse.y lex.yy.c
 lex.yy.c: lex.l
        $(LEX) lex.l
 
-libcgroup.so: api.c libcgroup.h wrapper.c
+libcgroup.so: api.c libcgroup.h wrapper.c config.c lex.yy.c y.tab.c
        $(CC) $(CFLAGS) -shared -fPIC -Wl,--soname,$@.$(VERSION) -o $@ api.c \
-               wrapper.c
+       wrapper.c lex.yy.c y.tab.c config.c
        ln -sf $@ $@.$(VERSION)
 
 test:
diff --git a/api.c b/api.c
index 2cd1a3735c30169d905c77b46517edc62da51f74..ff2a30a24fa87f8d1a36384f2143d6679ef4898a 100644 (file)
--- a/api.c
+++ b/api.c
@@ -658,7 +658,7 @@ static char *cg_build_path_locked(char *name, char *path, char *type)
        return NULL;
 }
 
-static char *cg_build_path(char *name, char *path, char *type)
+char *cg_build_path(char *name, char *path, char *type)
 {
        pthread_rwlock_rdlock(&cg_mount_table_lock);
        path = cg_build_path_locked(name, path, type);
@@ -790,6 +790,76 @@ int cgroup_attach_task(struct cgroup *cgroup)
        return error;
 }
 
+/**
+ * cg_mkdir_p, emulate the mkdir -p command (recursively creating paths)
+ * @path: path to create
+ */
+static int cg_mkdir_p(const char *path)
+{
+       char *real_path, *wd;
+       int i = 0, j = 0;
+       char pos, *str;
+       int ret = 0;
+       char cwd[FILENAME_MAX], *buf;
+
+       buf = getcwd(cwd, FILENAME_MAX);
+       if (!buf)
+               return ECGOTHER;
+
+       real_path = strdup(path);
+       if (!real_path)
+               return ECGOTHER;
+
+       do {
+               while (real_path[j] != '\0' && real_path[j] != '/')
+                       j++;
+               while (real_path[j] != '\0' && real_path[j] == '/')
+                       j++;
+               if (i == j)
+                       continue;
+               pos = real_path[j];
+               real_path[j] = '\0';            /* Temporarily overwrite "/" */
+               str = &real_path[i];
+               ret = mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+               wd = strdup(str);
+               if (!wd) {
+                       ret = ECGOTHER;
+                       break;
+               }
+               real_path[j] = pos;
+               if (ret) {
+                       switch (errno) {
+                       case EEXIST:
+                               ret = 0;        /* Not fatal really */
+                               break;
+                       case EPERM:
+                               ret = ECGROUPNOTOWNER;
+                               free(wd);
+                               goto done;
+                       default:
+                               ret = ECGROUPNOTALLOWED;
+                               free(wd);
+                               goto done;
+                       }
+               }
+               i = j;
+               ret = chdir(wd);
+               if (ret) {
+                       printf("could not chdir to child directory (%s)\n", wd);
+                       break;
+               }
+               free(wd);
+       } while (real_path[i]);
+
+       ret = chdir(buf);
+       if (ret)
+               printf("could not go back to old directory (%s)\n", cwd);
+
+done:
+       free(real_path);
+       return ret;
+}
+
 /*
  * create_control_group()
  * This is the basic function used to create the control group. This function
@@ -801,21 +871,7 @@ static int cg_create_control_group(char *path)
        int error;
        if (!cg_test_mounted_fs())
                return ECGROUPNOTMOUNTED;
-       error = mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
-       if (error) {
-               switch(errno) {
-               case EEXIST:
-                       /*
-                        * If the directory already exists, it really should
-                        * not be an error
-                        */
-                       return 0;
-               case EPERM:
-                       return ECGROUPNOTOWNER;
-               default:
-                       return ECGROUPNOTALLOWED;
-               }
-       }
+       error = cg_mkdir_p(path);
        return error;
 }
 
@@ -1065,7 +1121,7 @@ int cgroup_create_cgroup(struct cgroup *cgroup, int ignore_ownership)
                        strcat(path, "/tasks");
                        error = chown(path, cgroup->tasks_uid,
                                                        cgroup->tasks_gid);
-                       if (!error) {
+                       if (error) {
                                error = ECGFAIL;
                                goto err;
                        }
diff --git a/cgconfig.c b/cgconfig.c
new file mode 100644 (file)
index 0000000..b98769f
--- /dev/null
@@ -0,0 +1,55 @@
+
+/*
+ * Copyright IBM Corporation. 2007
+ *
+ * Authors:    Dhaval Giani <dhaval@linux.vnet.ibm.com>
+ *             Balbir Singh <balbir@linux.vnet.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Code initiated and designed by Dhaval Giani. All faults are most likely
+ * his mistake.
+ */
+
+#include <libcgroup.h>
+#include <libcgroup-internal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+       int c;
+       char filename[PATH_MAX];
+       int ret;
+
+       if (argc < 2) {
+               fprintf(stderr, "usage is %s <option> <config file>\n",
+                       argv[0]);
+               exit(2);
+       }
+
+       while ((c = getopt(argc, argv, "l:")) > 0) {
+               switch (c) {
+               case 'l':
+                       strncpy(filename, optarg, PATH_MAX);
+                       ret = cgroup_config_load_config(filename);
+                       if (ret) {
+                               printf("Loading configuration file %s "
+                                       "failed, ret = %d\n", filename, ret);
+                               exit(3);
+                       }
+                       break;
+               default:
+                       fprintf(stderr, "Invalid command line option\n");
+                       break;
+               }
+       }
+       return 0;
+}
index b0d4604961561254018b94298a33ad16ba54c6fe..baaf7d80b7a8f8846df2cb66ef2452abf07dc914 100644 (file)
--- a/config.c
+++ b/config.c
@@ -20,6 +20,9 @@
  *
  * Code initiated and designed by Balbir Singh. All faults are most likely
  * his mistake.
+ *
+ * Cleanup and changes to use the "official" structures and functions made
+ * by Dhaval Giani. All faults will still be Balbir's mistake :)
  */
 
 #include <assert.h>
 #include <errno.h>
 #include <grp.h>
 #include <libcgroup.h>
+#include <libcgroup-internal.h>
 #include <limits.h>
 #include <pwd.h>
+#include <pthread.h>
 #include <search.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#define MAX_CGROUPS 1024
+
 extern FILE *yyin;
 extern int yyparse(void);
-extern int yydebug;
-extern int line_no;
-extern int verbose;
-
-struct hsearch_data group_hash;
-struct list_of_names *group_list;
-struct mount_table *mount_table;
-
-const char library_ver[] = "0.01";
-const char cg_filesystem[] = "cgroup";
-
-struct cg_group *current_group;
-
-const char *cg_controller_names[] = {
-       "cpu",
-       "cpuacct",
-       "memory",
-       "cpuset",
-       NULL,
-};
 
 /*
- * File traversal routines require the maximum number of open file
- * descriptors to be specified
+ * The basic global data structures.
+ *
+ * config_mount_table -> Where what controller is mounted
+ * table_index -> Where in the table are we.
+ * config_table_lock -> Serializing access to config_mount_table.
+ * cgroup_table -> Which cgroups have to be created.
+ * cgroup_table_index -> Where in the cgroup_table we are.
  */
-const int cg_max_openfd = 20;
+static struct cg_mount_table_s config_mount_table[CG_CONTROLLER_MAX];
+static int config_table_index;
+static pthread_rwlock_t config_table_lock = PTHREAD_RWLOCK_INITIALIZER;
+static struct cgroup config_cgroup_table[MAX_CGROUPS];
+int cgroup_table_index;
 
 /*
- * Insert the group into the list of group names we maintain. This helps
- * us cleanup nicely
+ * Needed for the type while mounting cgroupfs.
  */
-int cg_insert_into_group_list(const char *name)
-{
-       struct list_of_names *tmp, *curr;
-
-       tmp = malloc(sizeof(*tmp));
-       if (!tmp)
-               return 0;
-       tmp->next = NULL;
-       tmp->name = (char *)name;
+static const char cgroup_filesystem[] = "cgroup";
 
-       if (!group_list) {
-               group_list = tmp;
-               return 1;
-       }
-       curr = group_list;
-       while (curr->next)
-               curr = curr->next;
-
-       curr->next = tmp;
-       return 1;
-}
+/*
+ * NOTE: All these functions return 1 on success
+ * and not 0 as is the library convention
+ */
 
 /*
- * Cleanup the group list. We walk the group list and free the entries in the
- * hash tables and controller specific entries.
+ * This call just sets the name of the cgroup. It will
+ * always be called in the end, because the parser will
+ * work bottom up.
  */
-int cg_cleanup_group_list(void)
+int cgroup_config_insert_cgroup(char *cg_name)
 {
-       struct list_of_names *curr = group_list, *tmp;
-       ENTRY item, *found_item;
-       int ret;
-       struct cg_group *cg_group;
-
-       while (curr) {
-               tmp = curr;
-               curr = curr->next;
-               item.key = tmp->name;
-               ret = hsearch_r(item, FIND, &found_item, &group_hash);
-               if (!ret) {
-                       printf("Most likely a bug in the code\n");
-                       continue;
-               }
-               /*
-                * Free the name and it's value
-                */
-               free(tmp->name);
-               cg_group = (struct cg_group *)found_item->data;
-               /*
-                * Controller specific cleanup
-                */
-               if (cg_group->cpu_config.shares)
-                       free(cg_group->cpu_config.shares);
-
-               free(found_item->data);
-       }
+       struct cgroup *config_cgroup =
+                       &config_cgroup_table[cgroup_table_index];
 
+       strncpy(config_cgroup->name, cg_name, FILENAME_MAX);
+       /*
+        * Since this will be the last part to be parsed.
+        */
+       cgroup_table_index++;
+       free(cg_name);
        return 1;
 }
 
 /*
- * Find and walk the mount_table structures to find the specified controller
- * name. This routine is *NOT* thread safe.
+ * This function sets the various controller's control
+ * files. It will always append values for cgroup_table_index
+ * entry in the cgroup_table. The index is incremented in
+ * cgroup_config_insert_cgroup
  */
-struct mount_table *cg_find_mount_info(const char *controller_name)
+int cgroup_config_parse_controller_options(char *controller, char *name_value)
 {
-       struct mount_table *curr = mount_table;
-       char *str;
-
-       while (curr) {
-               dbg("options %s mntpt %s next %p\n", curr->options,
-                       curr->mount_point, curr->next);
-               dbg("passed controller name %s\n", controller_name);
-               str = curr->options;
-               if (!str)
-                       return NULL;
-
-               str = strtok(curr->options, ",");
-               do {
-                       if (!strcmp(str, controller_name))
-                               return curr;
-                       str = strtok(NULL, ",");
-               } while(str);
-               curr = curr->next;
-       }
-       return NULL;
-}
+       char *buffer;
+       char *name, *value;
+       struct cgroup_controller *cgc;
+       int error;
+       struct cgroup *config_cgroup =
+               &config_cgroup_table[cgroup_table_index];
 
-int cg_cpu_controller_settings(struct cg_group *cg_group,
-                               const char *group_path)
-{
-       int ret = 1;
-       char *shares_file;
+       cgc = cgroup_add_controller(config_cgroup, controller);
 
-       shares_file = malloc(strlen(group_path) + strlen("/cpu.shares") + 1);
-       if (!shares_file)
-               return 0;
+       if (!cgc)
+               goto parse_error;
 
-       strcpy(shares_file, group_path);
-       shares_file = strcat(shares_file, "/cpu.shares");
-       dbg("shares file is %s\n", shares_file);
-       if (cg_group->cpu_config.shares) {
-               FILE *fd = fopen(shares_file, "rw+");
-               if (!fd)
-                       goto cleanup_shares;
-               /*
-                * Assume that one write will do it for us
-                */
-               fwrite(cg_group->cpu_config.shares,
-                       strlen(cg_group->cpu_config.shares), 1, fd);
-               fclose(fd);
-       }
-cleanup_shares:
-       free(shares_file);
-       return ret;
-}
+       /*
+        * Did we just specify the controller to create the correct
+        * set of directories, without setting any values?
+        */
+       if (!name_value)
+               goto done;
 
-int cg_controller_handle_option(struct cg_group *cg_group,
-                               const char *cg_controller_name,
-                               const char *group_path)
-{
-       int ret = 0;
-       if (!strncmp(cg_controller_name, "cpu", strlen("cpu"))) {
-               ret = cg_cpu_controller_settings(cg_group, group_path);
-       } else
-               printf("config for %s pending\n", cg_controller_name);
-       return ret;
-}
+       name = strtok_r(name_value, " ", &buffer);
 
-int cg_create_group(struct cg_group *cg_group)
-{
-       int i, ret;
-       struct mount_table *mount_info;
-       char *group_path[2], *tasks_file, *shares_file;
+       if (!name)
+               goto parse_error;
 
-       dbg("found group %s\n", cg_group->name);
-       group_path[1] = NULL;
+       value = strtok_r(NULL, " ", &buffer);
 
-       for (i = 0; cg_controller_names[i]; i++) {
+       if (!value)
+               goto parse_error;
 
-               /*
-                * Find the mount point related information
-                */
-               mount_info = cg_find_mount_info(cg_controller_names[i]);
-               if (!mount_info)
-                       continue;
 
-               dbg("mount_info for controller %s:%s\n",
-                       mount_info->mount_point, cg_controller_names[i]);
-               /*
-                * TODO: Namespace support is most likely going to be
-                * plugged in here
-                */
+       error = cgroup_add_value_string(cgc, name, value);
 
-               /*
-                * Find the path to the group directory
-                */
-               group_path[0] = cg_build_group_path(cg_group, mount_info);
-               if (!group_path[0])
-                       goto cleanup_group;
-               /*
-                * Create the specified directory. Errors are ignored.
-                * If the directory already exists, we are most likely
-                * OK
-                */
-               ret = cg_make_directory(cg_group, group_path);
-               if (!ret && (errno != EEXIST))
-                       goto cleanup_dir;
+       if (error)
+               goto parse_error;
 
-               /*
-                * Find the tasks file, should probably be encapsulated
-                * like we encapsulate cg_build_group_path
-                */
-               tasks_file = malloc(strlen(group_path[0]) + strlen("/tasks") + 1);
-               if (!tasks_file)
-                       goto cleanup_dir;
-               strcpy(tasks_file, group_path[0]);
-               tasks_file = strncat(tasks_file, "/tasks", strlen("/tasks"));
-               dbg("tasks file is %s\n", tasks_file);
-
-               /*
-                * Assign task file ownership
-                */
-               ret = chown(tasks_file, cg_group->tasks_uid,
-                               cg_group->tasks_gid);
-               if (ret < 0)
-                       goto cleanup_perm;
-
-               /*
-                * Controller specific work, errors are not fatal.
-                */
-               cg_controller_handle_option(cg_group, cg_controller_names[i],
-                                               group_path[0]);
-               free(tasks_file);
-               free(group_path[0]);
-       }
+done:
+       free(controller);
+       free(name_value);
        return 1;
-cleanup_perm:
-       rmdir(group_path[0]);
-cleanup_dir:
-       free(group_path[0]);
-cleanup_group:
+
+parse_error:
+       free(controller);
+       free(name_value);
+       cgroup_delete_cgroup(config_cgroup, 1);
+       cgroup_table_index--;
        return 0;
 }
 
 /*
- * Go ahead and create the groups in the filesystem. This routine will need
- * to be revisited everytime new controllers are added.
+ * Sets the tasks file's uid and gid
  */
-int cg_create_groups(void)
+int cgroup_config_group_task_perm(char *perm_type, char *value)
 {
-       struct list_of_names *curr = group_list, *tmp;
-       ENTRY item, *found_item;
-       struct cg_group *cg_group;
-       int ret = 1;
-
-       while (curr) {
-               tmp = curr;
-               curr = curr->next;
-               item.key = tmp->name;
-               ret = hsearch_r(item, FIND, &found_item, &group_hash);
-               if (!ret)
-                       return 0;
-               cg_group = (struct cg_group *)found_item->data;
-               ret = cg_create_group(cg_group);
-               if (!ret)
-                       break;
+       struct passwd *pw, *pw_buffer;
+       struct group *group, *group_buffer;
+       int error;
+       long val = atoi(value);
+       char buffer[CGROUP_BUFFER_LEN];
+       struct cgroup *config_cgroup =
+                       &config_cgroup_table[cgroup_table_index];
+
+       if (!strcmp(perm_type, "uid")) {
+               if (!val) {
+                       pw = (struct passwd *) malloc(sizeof(struct passwd));
+
+                       if (!pw)
+                               goto group_task_error;
+
+                       error = getpwnam_r(value, pw, buffer, CGROUP_BUFFER_LEN,
+                                                               &pw_buffer);
+                       if (pw_buffer == NULL) {
+                               free(pw);
+                               goto group_task_error;
+                       }
+
+                       val = pw->pw_uid;
+                       free(pw);
+               }
+               config_cgroup->tasks_uid = val;
        }
 
-       return ret;
-}
+       if (!strcmp(perm_type, "gid")) {
+               if (!val) {
+                       group = (struct group *) malloc(sizeof(struct group));
 
-/*
- * Go ahead and create the groups in the filesystem. This routine will need
- * to be revisited everytime new controllers are added.
- */
-int cg_destroy_groups(void)
-{
-       struct list_of_names *curr = group_list, *tmp;
-       ENTRY item, *found_item;
-       struct cg_group *cg_group;
-       int ret;
-       struct mount_table *mount_info;
-       char *group_path;
-
-       while (curr) {
-               tmp = curr;
-               curr = curr->next;
-               item.key = tmp->name;
-               ret = hsearch_r(item, FIND, &found_item, &group_hash);
-               if (!ret)
-                       return 0;
-               cg_group = (struct cg_group *)found_item->data;
-               mount_info = cg_find_mount_info("cpu");
-               dbg("mount_info for cpu %s\n", mount_info->mount_point);
-               if (!mount_info)
-                       return 0;
-               group_path = malloc(strlen(mount_info->mount_point) +
-                               strlen(cg_group->name) + 2);
-               if (!group_path)
-                       return 0;
-               strncpy(group_path, mount_info->mount_point,
-                                       strlen(mount_info->mount_point) + 1);
-               dbg("group_path is %s\n", group_path);
-               strncat(group_path, "/", strlen("/"));
-               strncat(group_path, cg_group->name, strlen(cg_group->name));
-               dbg("group_path is %s\n", group_path);
-               /*
-                * We might strategically add migrate tasks here, so that
-                * rmdir is successful. TODO: Later
-                */
-               ret = rmdir(group_path);
-               if (ret < 0)
-                       goto err;
+                       if (!group)
+                               goto group_task_error;
+
+                       error = getgrnam_r(value, group, buffer,
+                                       CGROUP_BUFFER_LEN, &group_buffer);
+
+                       if (group_buffer == NULL) {
+                               free(group);
+                               goto group_task_error;
+                       }
+
+                       val = group->gr_gid;
+                       free(group);
+               }
+               config_cgroup->tasks_gid = val;
        }
 
        return 1;
-err:
-       free(group_path);
+
+group_task_error:
+       free(perm_type);
+       free(value);
+       cgroup_delete_cgroup(config_cgroup, 1);
+       cgroup_table_index--;
        return 0;
 }
+
 /*
- * The cg_get_current_group routine is used by the parser to figure out
- * the current group that is being built and fill it in with the information
- * as it parses through the configuration file
+ * Set the control file's uid/gid
  */
-struct cg_group *cg_get_current_group(void)
+int cgroup_config_group_admin_perm(char *perm_type, char *value)
 {
-       if (!current_group)
-               current_group = calloc(1, sizeof(*current_group));
+       struct passwd *pw, *pw_buffer;
+       struct group *group, *group_buffer;
+       int error;
+       struct cgroup *config_cgroup =
+                               &config_cgroup_table[cgroup_table_index];
+       long val = atoi(value);
+       char buffer[CGROUP_BUFFER_LEN];
 
-       return current_group;
-}
+       if (!strcmp(perm_type, "uid")) {
+               if (!val) {
+                       pw = (struct passwd *) malloc(sizeof(struct passwd));
 
-/*
- * This routine should be invoked when the current group being parsed is
- * completely parsed
- */
-void cg_put_current_group(void)
-{
-       /*
-        * NOTE: we do not free the group, the group is installed into the
-        * hash table, the cleanup routine will do the freeing of the group
-        */
-       current_group = NULL;
-}
+                       if (!pw)
+                               goto admin_error;
 
-int cg_insert_group(const char *group_name)
-{
-       struct cg_group *cg_group = cg_get_current_group();
-       ENTRY item, *found_item;
-       int ret;
+                       error = getpwnam_r(value, pw, buffer, CGROUP_BUFFER_LEN,
+                                                               &pw_buffer);
+                       if (error) {
+                               free(pw);
+                               goto admin_error;
+                       }
 
-       if (!cg_group)
-               return 0;
-       /*
-        * Dont' copy the name over, just point to it
-        */
-       cg_group->name = (char *)group_name;
-       item.key = (char *)group_name;
-       item.data = cg_group;
-       dbg("Inserting %s into hash table\n", group_name);
-       ret = hsearch_r(item, ENTER, &found_item, &group_hash);
-       if (!ret) {
-               if (found_item)
-                       errno = EEXIST;
-               errno = ENOMEM;
-               goto err;
+                       val = pw->pw_uid;
+                       free(pw);
+               }
+               config_cgroup->control_uid = val;
        }
-       ret = cg_insert_into_group_list(group_name);
-       if (!ret)
-               goto err;
-       dbg("Inserted %s into hash and list\n", group_name);
-       cg_put_current_group();
+
+       if (!strcmp(perm_type, "gid")) {
+               if (!val) {
+                       group = (struct group *) malloc(sizeof(struct group));
+
+                       if (!group)
+                               goto admin_error;
+
+                       error = getgrnam_r(value, group, buffer,
+                                       CGROUP_BUFFER_LEN, &group_buffer);
+
+                       if (error) {
+                               free(group);
+                               goto admin_error;
+                       }
+
+                       val = group->gr_gid;
+                       free(group);
+               }
+               config_cgroup->control_gid = val;
+       }
+
        return 1;
-err:
-       cg_cleanup_group_list();
+
+admin_error:
+       free(perm_type);
+       free(value);
+       cgroup_delete_cgroup(config_cgroup, 1);
+       cgroup_table_index--;
        return 0;
 }
 
 /*
- * Because of the way parsing works (bottom-up, shift-reduce), we don't
- * know the name of the controller yet. Compilers build an AST and use
- * a symbol table to deal with this problem. This code does simple things
- * like concatinating strings and passing them upwards. This routine is
- * *NOT* thread safe.
- *
- * This code will need modification everytime new controller support is
- * added.
+ * The moment we have found the controller's information
+ * insert it into the config_mount_table.
  */
-int cg_parse_controller_options(char *controller, char *name_value)
+int cgroup_config_insert_into_mount_table(char *name, char *mount_point)
 {
-       struct cg_group *cg_group = cg_get_current_group();
-       char *name, *value;
+       int i;
 
-       if (!cg_group)
+       if (config_table_index >= CG_CONTROLLER_MAX)
                return 0;
 
-       if (!strncmp(controller, "cpu", strlen("cpu"))) {
-               name = strtok(name_value, " ");
-               value = strtok(NULL, " ");
-               if (!strncmp(name, "cpu.shares", strlen("cpu.shares")))
-                       cg_group->cpu_config.shares = strdup(value);
-               else {
-                       free(controller);
-                       free(name_value);
-                       return 0;
+       pthread_rwlock_wrlock(&config_table_lock);
+
+       /*
+        * 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) {
+                       char *cname = config_mount_table[i].name;
+                       strncat(cname, ",", FILENAME_MAX - strlen(cname) - 1);
+                       strncat(cname, name,
+                                       FILENAME_MAX - strlen(cname) - 1);
+                       goto done;
                }
-               dbg("cpu name %s value %s\n", name, value);
-       } else {
-               return 0;
        }
-       free(controller);
-       free(name_value);
+
+       strcpy(config_mount_table[config_table_index].name, name);
+       strcpy(config_mount_table[config_table_index].path, mount_point);
+       config_table_index++;
+done:
+       pthread_rwlock_unlock(&config_table_lock);
+       free(name);
+       free(mount_point);
        return 1;
 }
 
 /*
- * Convert the uid/gid field and supplied value to appropriate task
- * permissions. This routine is *NOT* thread safe.
+ * Cleanup all the data from the config_mount_table
  */
-int cg_group_task_perm(char *perm_type, char *value)
+void cgroup_config_cleanup_mount_table(void)
 {
-       struct cg_group *cg_group = cg_get_current_group();
-       struct passwd *pw;
-       struct group *group;
-       long val = atoi(value);
-       if (!strncmp(perm_type, "uid", strlen("uid"))) {
-               if (!val) {     /* We got the identifier as a name */
-                       pw = getpwnam(value);
-                       if (!pw) {
-                               free(perm_type);
-                               free(value);
-                               return 0;
-                       } else {
-                               cg_group->tasks_uid = pw->pw_uid;
-                       }
-               } else {
-                       cg_group->tasks_uid = val;
-               }
-               dbg("TASKS %s: %d\n", perm_type, cg_group->tasks_uid);
-       }
-       if (!strncmp(perm_type, "gid", strlen("gid"))) {
-               if (!val) {     /* We got the identifier as a name */
-                       group = getgrnam(value);
-                       if (!group) {
-                               free(perm_type);
-                               free(value);
-                               return 0;
-                       } else {
-                               cg_group->tasks_gid = group->gr_gid;
-                       }
-               } else {
-                       cg_group->tasks_gid = val;
-               }
-               dbg("TASKS %s: %d\n", perm_type, cg_group->tasks_gid);
-       }
-       free(perm_type);
-       free(value);
-       return 1;
-}
-
-int cg_group_admin_perm(char *perm_type, char *value)
-{
-       struct cg_group *cg_group = cg_get_current_group();
-       struct passwd *pw;
-       struct group *group;
-       long val = atoi(value);
-       if (!strncmp(perm_type, "uid", strlen("uid"))) {
-               if (!val) {     /* We got the identifier as a name */
-                       pw = getpwnam(value);
-                       if (!pw) {
-                               free(perm_type);
-                               free(value);
-                               return 0;
-                       } else {
-                               cg_group->admin_uid = pw->pw_uid;
-                       }
-               } else {
-                       cg_group->admin_uid = val;
-               }
-               dbg("ADMIN %s: %d\n", perm_type, cg_group->admin_uid);
-       }
-       if (!strncmp(perm_type, "gid", strlen("gid"))) {
-               if (!val) {     /* We got the identifier as a name */
-                       group = getgrnam(value);
-                       if (!group) {
-                               free(perm_type);
-                               free(value);
-                               return 0;
-                       } else {
-                               cg_group->admin_gid = group->gr_gid;
-                       }
-               } else {
-                       cg_group->admin_gid = val;
-               }
-               dbg("ADMIN %s: %d\n", perm_type,
-                                                       cg_group->admin_gid);
-       }
-       free(perm_type);
-       free(value);
-       return 1;
+       memset(&config_mount_table, 0,
+                       sizeof(struct cg_mount_table_s) * CG_CONTROLLER_MAX);
 }
 
 /*
- * We maintain a hash table. The group hash table maintains the parameters for
- * each group, including the parameters for each controller
- *
- * TODO: Make the initialization a run time configuration parameter
+ * Start mounting the mount table.
  */
-int cg_init_group_and_mount_info(void)
+int cgroup_config_mount_fs()
 {
        int ret;
+       struct stat buff;
+       int i;
 
-       group_list = NULL;
-       mount_table = NULL;
-       current_group = NULL;
+       for (i = 0; i < config_table_index; i++) {
+               struct cg_mount_table_s *curr = &(config_mount_table[i]);
 
-       ret = hcreate_r(MAX_GROUP_ELEMENTS, &group_hash);
-       if (!ret)
-               return 0;
-       return 1;
+               ret = stat(curr->path, &buff);
+
+               if (ret < 0 && errno != ENOENT)
+                       return ECGOTHER;
+
+               if (errno == ENOENT) {
+                       ret = mkdir(curr->path,
+                                       S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+                       if (ret < 0)
+                               return ECGOTHER;
+               } else if (!S_ISDIR(buff.st_mode)) {
+                       errno = ENOTDIR;
+                       return ECGOTHER;
+               }
+
+               ret = mount(cgroup_filesystem, curr->path, cgroup_filesystem,
+                                                               0, curr->name);
+
+               if (ret < 0)
+                       return ECGMOUNTFAIL;
+       }
+       return 0;
 }
 
 /*
- * This routine should be called only once all elements of the hash table have
- * been freed. Otherwise, we'll end up with a memory leak.
+ * Actually create the groups once the parsing has been finished.
  */
-void cg_destroy_group_and_mount_info(void)
+int cgroup_config_create_groups()
 {
-       hdestroy_r(&group_hash);
-       group_list = NULL;
-       mount_table = NULL;
-       current_group = NULL;
+       int error = 0;
+       int i;
+
+       for (i = 0; i < cgroup_table_index; i++) {
+               struct cgroup *cgroup = &config_cgroup_table[i];
+               error = cgroup_create_cgroup(cgroup, 0);
+               dbg("creating group %s, error %d\n", cgroup->name, error);
+               if (error)
+                       return error;
+       }
+       return error;
 }
 
 /*
- * Insert a name, mount_point pair into the mount_table data structure
- * TODO: Validate names and mount points
+ * Destroy the cgroups
  */
-int cg_insert_into_mount_table(const char *name, const char *mount_point)
+int cgroup_config_destroy_groups(void)
 {
-       struct mount_table *tmp, *prev = mount_table;
-
-       while (prev && prev->next != NULL &&
-               (strncmp(mount_point, prev->mount_point, strlen(mount_point))))
-               prev = prev->next;
-
-       if (prev &&
-               !(strncmp(mount_point, prev->mount_point, strlen(mount_point)))) {
-               prev->options = realloc(prev->options, strlen(prev->options)
-                                                       + strlen(name) + 2);
-               if (!prev->options)
-                       return 0;
-               strncat(prev->options, ",", strlen(","));
-               strncat(prev->options, name, strlen(name));
-               dbg("options %s: mount_point %s\n", prev->options,
-                                                       prev->mount_point);
-               return 1;
-       }
-
-       tmp = malloc(sizeof(*tmp));
-       if (!tmp)
-               return 0;
-
-       tmp->next = NULL;
-       tmp->mount_point = (char *)mount_point;
-       tmp->options = (char *)name;
-       dbg("options %s: mount_point %s\n", tmp->options, tmp->mount_point);
-
-       if (!prev) {
-               mount_table = tmp;
-               return 1;
-       } else {
-               prev->next = tmp;
+       int error = 0;
+       int i;
+
+       for (i = 0; i < cgroup_table_index; i++) {
+               struct cgroup *cgroup = &config_cgroup_table[i];
+               error = cgroup_delete_cgroup(cgroup, 0);
+               if (error)
+                       return error;
        }
-
-       return 1;
+       return error;
 }
 
-void cg_cleanup_mount_table(void)
+/*
+ * Unmount the controllers
+ */
+int cgroup_config_unmount_controllers(void)
 {
-       struct mount_table *curr = mount_table, *tmp;
-
-       while (curr) {
-               tmp = curr;
-               curr = curr->next;
-               tmp->next = NULL;
+       int i;
+       int error;
 
+       for (i = 0; i < config_table_index; i++) {
                /*
-                * Some of this data might have been allocated by the lexer
-                * while parsing tokens
+                * We ignore failures and ensure that all mounted
+                * containers are unmounted
                 */
-               free(tmp->mount_point);
-               free(tmp->options);
-
-               free(tmp);
+               error = umount(config_mount_table[i].path);
+               if (error < 0)
+                       dbg("Unmount failed\n");
+               error = rmdir(config_mount_table[i].path);
+               if (error < 0)
+                       dbg("rmdir failed\n");
        }
+
+       return 0;
 }
 
-int cg_load_config(const char *pathname)
+/*
+ * The main function which does all the setup of the data structures
+ * and finally creates the cgroups
+ */
+int cgroup_config_load_config(const char *pathname)
 {
-       yyin = fopen(pathname, "rw");
+       int error;
+       yyin = fopen(pathname, "r");
+
        if (!yyin) {
                dbg("Failed to open file %s\n", pathname);
-               return 0;
+               return ECGOTHER;
        }
 
-       if (!cg_init_group_and_mount_info())
-               return 0;
-
        if (yyparse() != 0) {
                dbg("Failed to parse file %s\n", pathname);
-               return 0;
+               return ECGROUPPARSEFAIL;
        }
 
-       if (!cg_mount_controllers())
+       error = cgroup_config_mount_fs();
+       if (error)
+               goto err_mnt;
+
+       error = cgroup_init();
+       if (error)
                goto err_mnt;
-       if (!cg_create_groups())
+
+       error = cgroup_config_create_groups();
+       dbg("creating all cgroups now, error=%d\n", error);
+       if (error)
                goto err_grp;
 
        fclose(yyin);
-       return 1;
+       return 0;
 err_grp:
-       dbg("Creating groups failed\n");
-       cg_destroy_groups();
-       cg_cleanup_group_list();
+       cgroup_config_destroy_groups();
 err_mnt:
-       dbg("Mounting controllers failed\n");
-       cg_unmount_controllers();
-       cg_cleanup_mount_table();
+       cgroup_config_unmount_controllers();
        fclose(yyin);
-       return 0;
-}
-
-void cg_unload_current_config(void)
-{
-       cg_destroy_groups();
-       cg_cleanup_group_list();
-       cg_unmount_controllers();
-       cg_cleanup_mount_table();
-       cg_destroy_group_and_mount_info();
-}
-
-int main(int argc, char *argv[])
-{
-       int c;
-       char filename[PATH_MAX];
-       int ret;
-
-       if (argc < 2) {
-               fprintf(stderr, "usage is %s <option> <config file>\n",
-                       argv[0]);
-               exit(2);
-       }
-
-       while ((c = getopt(argc, argv, "l:ur:")) > 0) {
-               switch (c) {
-               case 'u':
-                       cg_unload_current_config();
-                       break;
-               case 'r':
-                       cg_unload_current_config();
-                       /* FALLTHROUGH */
-               case 'l':
-                       strncpy(filename, optarg, PATH_MAX);
-                       ret = cg_load_config(filename);
-                       if (!ret)
-                               exit(3);
-                       break;
-               default:
-                       fprintf(stderr, "Invalid command line option\n");
-                       break;
-               }
-       }
-
+       return error;
 }
diff --git a/file-ops.c b/file-ops.c
deleted file mode 100644 (file)
index ffba8e8..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright IBM Corporation. 2007
- *
- * Authors:    Balbir Singh <balbir@linux.vnet.ibm.com>
- *             Dhaval Giani <dhaval@linux.vnet.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-#include <dirent.h>
-#include <errno.h>
-#include <fts.h>
-#include <grp.h>
-#include <libcgroup.h>
-#include <limits.h>
-#include <pwd.h>
-#include <search.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-extern const char cg_filesystem[];
-extern struct mount_table *mount_table;
-
-int cg_chown_file(FTS *fts, FTSENT *ent, uid_t owner, gid_t group)
-{
-       int ret = 1;
-       const char *filename = fts->fts_path;
-       dbg("seeing file %s\n", filename);
-       switch (ent->fts_info) {
-       case FTS_ERR:
-               errno = ent->fts_errno;
-               break;
-       case FTS_D:
-       case FTS_DC:
-       case FTS_NSOK:
-       case FTS_NS:
-       case FTS_DNR:
-       case FTS_DP:
-       case FTS_F:
-       case FTS_DEFAULT:
-               ret = chown(filename, owner, group);
-               break;
-       }
-       return ret;
-}
-
-/*
- * TODO: Need to decide a better place to put this function.
- */
-int cg_chown_recursive(char *path[], uid_t owner, gid_t group)
-{
-       int ret = 1;
-       FTS *fts = fts_open((char **)path, FTS_PHYSICAL | FTS_NOCHDIR |
-                               FTS_NOSTAT, NULL);
-       while (1) {
-               FTSENT *ent;
-               ent = fts_read(fts);
-               if (!ent) {
-                       dbg("fts_read failed\n");
-                       break;
-               }
-               cg_chown_file(fts, ent, owner, group);
-       }
-       fts_close(fts);
-       return ret;
-}
-
-char *cg_build_group_path(struct cg_group *cg_group,
-                                       struct mount_table *mount_info)
-{
-       char *group_path;
-
-       group_path = malloc(strlen(mount_info->mount_point) +
-                                               strlen(cg_group->name) + 2);
-       if (!group_path)
-               return NULL;
-       strncpy(group_path, mount_info->mount_point,
-               strlen(mount_info->mount_point) + 1);
-       dbg("group path is %s\n", group_path);
-       strncat(group_path, "/", strlen("/"));
-       strncat(group_path, cg_group->name, strlen(cg_group->name));
-       dbg("group path is %s\n", group_path);
-       return group_path;
-}
-
-int cg_make_directory(struct cg_group *cg_group, char *group_path[])
-{
-       int ret;
-       ret = mkdir(group_path[0], S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
-       if (ret < 0)
-               return 0;
-       /*
-        * Recursively change all files under the directory
-        */
-       ret = cg_chown_recursive(group_path, cg_group->admin_uid,
-                                               cg_group->admin_gid);
-       return ret;
-}
-
-/*
- * After having parsed the configuration file, walk through the mount_table
- * and mount the specified controllers. This routine might create directories
- * specified as mount_point.
- */
-int cg_mount_controllers(void)
-{
-       int ret;
-       struct mount_table *curr = mount_table;
-       struct stat buf;
-
-       while (curr) {
-               ret = stat(curr->mount_point, &buf);
-               if (ret < 0 && errno != ENOENT)
-                       return 0;
-
-               /*
-                * Check if path needs to be created before mounting
-                */
-               if (errno == ENOENT) {
-                       ret = mkdir(curr->mount_point, S_IRWXU | S_IRWXG |
-                                       S_IRWXO | S_ISVTX);
-                       if (ret < 0)
-                               return 0;
-               } else if (!S_ISDIR(buf.st_mode)) {
-                       errno = ENOTDIR;
-                       return 0;
-               }
-
-               ret = mount(cg_filesystem, curr->mount_point,
-                                       cg_filesystem, 0, curr->options);
-
-               if (ret < 0)
-                       return 0;
-               curr = curr->next;
-       }
-       return 1;
-}
-
-/*
- * Called during end of WLM configuration to unmount all controllers or
- * on failure, to cleanup mounted controllers
- */
-int cg_unmount_controllers(void)
-{
-       struct mount_table *curr = mount_table;
-       int ret;
-
-       while (curr) {
-               /*
-                * We ignore failures and ensure that all mounted
-                * containers are unmounted
-                */
-               ret = umount(curr->mount_point);
-               if (ret < 0)
-                       printf("Unmount failed\n");
-               ret = rmdir(curr->mount_point);
-               if (ret < 0)
-                       printf("rmdir failed\n");
-               curr = curr->next;
-       }
-       return 1;
-}
-
index c2f2ce3160bd5b0bae1d262ef0b52947d96e1928..af5d396c72cf006675c37eb2acb889b218980145 100644 (file)
@@ -24,6 +24,8 @@ __BEGIN_DECLS
 #define CGRULES_CONF_FILE       "/etc/cgrules.conf"
 #define CGRULES_MAX_FIELDS_PER_LINE            3
 
+#define CGROUP_BUFFER_LEN (5 * FILENAME_MAX)
+
 struct control_value {
        char name[FILENAME_MAX];
        char value[CG_VALUE_MAX];
@@ -49,6 +51,7 @@ struct cgroup {
 struct cg_mount_table_s {
        char name[FILENAME_MAX];
        char path[FILENAME_MAX];
+       int index;
 };
 
 struct cgroup_rules_data {
@@ -78,6 +81,18 @@ struct cgroup_rule_list {
 };
 
 
+/* Internal API */
+char *cg_build_path(char *name, char *path, char *type);
+
+/*
+ * config related API
+ */
+int cgroup_config_insert_cgroup(char *cg_name);
+int cgroup_config_parse_controller_options(char *controller, char *name_value);
+int cgroup_config_group_task_perm(char *perm_type, char *value);
+int cgroup_config_group_admin_perm(char *perm_type, char *value);
+int cgroup_config_insert_into_mount_table(char *name, char *mount_point);
+void cgroup_config_cleanup_mount_table(void);
 __END_DECLS
 
 #endif
index 97c663dc6580f5ad00f0cea3d9b366cdd2102ad1..93258461e8ae4fd4435acd867c31af3a54791e10 100644 (file)
@@ -54,47 +54,6 @@ __BEGIN_DECLS
  * would require us to use a scanner/parser that can parse beyond ASCII
  */
 
-/*
- * These data structures are heavily controller dependent, which means
- * any changes (additions/removal) of configuration items would have to
- *  be reflected in this library. We might implement a plugin
- *  infrastructure, so that we can deal with such changes with ease.
- */
-
-struct cpu_controller {
-       /*TODO: Add the cpu.usage file here, also need to automate this.*/
-       char *shares;   /* Having strings helps us write them to files */
-       /*
-        * XX: No it does not make a difference. It requires a fprintf anyway
-        * so it needs the qualifier.
-        */
-};
-
-struct cg_group {
-       char *name;
-       uid_t tasks_uid;
-       gid_t tasks_gid;
-       uid_t admin_uid;
-       gid_t admin_gid;
-       struct cpu_controller cpu_config;
-};
-
-/*
- * A singly linked list suffices since we don't expect too many mount points
- */
-struct mount_table {
-       char *options;          /* Name(s) of the controller */
-       char *mount_point;      /* The place where the controller is mounted */
-       struct mount_table *next;
-};
-
-/*
- * Maintain a list of all group names. These will be used during cleanup
- */
-struct list_of_names {
-       char *name;
-       struct list_of_names *next;
-};
 
 /* Maximum length of a line in the daemon config file */
 #define CGROUP_RULE_MAXLINE (FILENAME_MAX + LOGIN_NAME_MAX + \
@@ -109,13 +68,6 @@ enum cgflags {
        CGFLAG_USECACHE = 0x01,
 };
 
-enum cg_msg_type {
-       CG_MSG_LOAD_FILE,
-       CG_MSG_UNLOAD_FILE,
-       CG_MSG_ERR,
-       CG_MSG_DONE,
-};
-
 enum cgroup_errors {
        ECGROUPNOTCOMPILED=50000,
        ECGROUPNOTMOUNTED,
@@ -141,35 +93,9 @@ enum cgroup_errors {
        ECGCONTROLLERNOTEQUAL,
        ECGROUPPARSEFAIL, /* Failed to parse rules configuration file. */
        ECGROUPNORULES, /* Rules list does not exist. */
+       ECGMOUNTFAIL,
 };
 
-#define CG_MAX_MSG_SIZE                256
-#define CG_SERVER_MSG_PATH     "/tmp/control_group"
-#define CG_BACKLOG             5
-
-/* Message's exchanged between server and client */
-struct cg_msg {
-       enum cg_msg_type type;
-       char buf[CG_MAX_MSG_SIZE];
-};
-
-/* Function Prototypes start here */
-int cg_init_group_and_mount_info(void);
-int cg_insert_into_mount_table(const char *name, const char *mount_point);
-void cg_cleanup_mount_table(void);
-int cg_group_admin_perm(char *perm_type, char *value);
-int cg_group_task_perm(char *perm_type, char *value);
-int cg_parse_controller_options(char *controller, char *name_value);
-int cg_insert_group(const char *group_name);
-int chown_recursive(const char* path, uid_t owner, gid_t group);
-int cg_make_directory(struct cg_group *cg_group, char *group_path[]);
-char *cg_build_group_path(struct cg_group *cg_group,
-                                       struct mount_table *mount_info);
-int cg_mount_controllers(void);
-int cg_unmount_controllers(void);
-int cg_load_config(const char *pathname);
-void cg_unload_current_config(void);
-
 #define CG_NV_MAX 100
 #define CG_CONTROLLER_MAX 100
 #define CG_VALUE_MAX 100
@@ -300,6 +226,10 @@ int cgroup_get_value_bool(struct cgroup_controller *controller,
                                                const char *name, bool *value);
 int cgroup_set_value_bool(struct cgroup_controller *controller,
                                                const char *name, bool value);
+/*
+ * Config related stuff
+ */
+int cgroup_config_load_config(const char *pathname);
 
 __END_DECLS
 
diff --git a/parse.y b/parse.y
index cfc86c8f50e6948f6faca54fdf14ed8e83117e4b..53141e9d83d7eb390cc07076e699e7843c65cdb5 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -18,6 +18,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <libcgroup.h>
+#include <libcgroup-internal.h>
 
 int yylex(void);
 extern int line_no;
@@ -67,7 +68,7 @@ group   :       GROUP ID '{' group_conf '}'
        {
                $$ = $4;
                if ($$)
-                       cg_insert_group($2);
+                       cgroup_config_insert_cgroup($2);
                else {
                        fprintf(stderr, "parsing failed at line number %d\n",
                                line_no);
@@ -80,7 +81,7 @@ group   :       GROUP ID '{' group_conf '}'
 group_conf
         :       ID '{' namevalue_conf '}'
        {
-               $$ = cg_parse_controller_options($1, $3);
+               $$ = cgroup_config_parse_controller_options($1, $3);
                if (!$$) {
                        fprintf(stderr, "parsing failed at line number %d\n",
                                line_no);
@@ -90,7 +91,7 @@ group_conf
        }
         |       group_conf ID '{' namevalue_conf '}' 
        {
-               $$ = cg_parse_controller_options($2, $4);
+               $$ = cgroup_config_parse_controller_options($2, $4);
                if (!$$) {
                        fprintf(stderr, "parsing failed at line number %d\n",
                                line_no);
@@ -125,12 +126,16 @@ namevalue_conf
                $$ = strncat($2, $4, strlen($4));
                free($4);
        }
+       |
+       {
+               $$ = NULL;
+       }
         ;
 
 task_namevalue_conf
         :       ID '=' ID ';'
        {
-               $$ = cg_group_task_perm($1, $3);
+               $$ = cgroup_config_group_task_perm($1, $3);
                if (!$$) {
                        fprintf(stderr, "parsing failed at line number %d\n",
                                line_no);
@@ -140,7 +145,7 @@ task_namevalue_conf
        }
         |       task_namevalue_conf ID '=' ID ';'
        {
-               $$ = $1 && cg_group_task_perm($2, $4);
+               $$ = $1 && cgroup_config_group_task_perm($2, $4);
                if (!$$) {
                        fprintf(stderr, "parsing failed at line number %d\n",
                                line_no);
@@ -153,7 +158,7 @@ task_namevalue_conf
 admin_namevalue_conf
         :       ID '=' ID ';'
        {
-               $$ = cg_group_admin_perm($1, $3);
+               $$ = cgroup_config_group_admin_perm($1, $3);
                if (!$$) {
                        fprintf(stderr, "parsing failed at line number %d\n",
                                line_no);
@@ -163,7 +168,7 @@ admin_namevalue_conf
        }
         |       admin_namevalue_conf ID '=' ID ';'
        {
-               $$ = $1 && cg_group_admin_perm($2, $4);
+               $$ = $1 && cgroup_config_group_admin_perm($2, $4);
                if (!$$) {
                        fprintf(stderr, "parsing failed at line number %d\n",
                                line_no);
@@ -223,8 +228,8 @@ task_conf:  TASK '{' task_namevalue_conf '}'
 mountvalue_conf
         :       ID '=' ID ';'
        {
-               if (!cg_insert_into_mount_table($1, $3)) {
-                       cg_cleanup_mount_table();
+               if (!cgroup_config_insert_into_mount_table($1, $3)) {
+                       cgroup_config_cleanup_mount_table();
                        $$ = 0;
                        return $$;
                }
@@ -232,8 +237,8 @@ mountvalue_conf
        }
         |       mountvalue_conf ID '=' ID ';'
        {
-               if (!cg_insert_into_mount_table($2, $4)) {
-                       cg_cleanup_mount_table();
+               if (!cgroup_config_insert_into_mount_table($2, $4)) {
+                       cgroup_config_cleanup_mount_table();
                        $$ = 0;
                        return $$;
                }
index 6738624364a351a6eb60e07bffd6f6f6818b2d25..a0e9a1bb3b8101111ebd40fb946dce72f7af0022 100644 (file)
@@ -32,6 +32,7 @@ group ca1 {
        memory {
                memory.limit_in_bytes = 200M;
        }
+
 }
 
 group default {
@@ -53,13 +54,15 @@ group default {
        memory {
                memory.limit_in_bytes = 200M;
        }
+
+       cpuacct {}
 }
 
 mount {
-       cpu = /container;
-       memory = /memory;
+       cpu = /cgroup/cpu;
+       memory = /cgroup/mem;
 }
 
 mount {
-       cpu_acct = /acct;
+       cpuacct = /cgroup/cpu;
 }