summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBalbir Singh <balbir@linux.vnet.ibm.com>2008-09-29 12:26:50 +0000
committerBalbir Singh <balbir@linux.vnet.ibm.com>2008-09-29 12:26:50 +0000
commitd1ab753ba5d0d641b52cb90e00ce2eabfae476f4 (patch)
tree984149374ff224629121be769d9e6a4e0eedcf63
parent1d00fc725ba26db40b2c792c75888c2ed777730d (diff)
Configuration rewrite to use the main cgroups API and several bug fixes
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
-rw-r--r--Makefile9
-rw-r--r--Makefile.in9
-rw-r--r--api.c90
-rw-r--r--cgconfig.c55
-rw-r--r--config.c854
-rw-r--r--file-ops.c176
-rw-r--r--libcgroup-internal.h15
-rw-r--r--libcgroup.h80
-rw-r--r--parse.y27
-rw-r--r--samples/wlm.conf.39
10 files changed, 480 insertions, 844 deletions
diff --git a/Makefile b/Makefile
index 380dde7..c92d48f 100644
--- 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:
diff --git a/Makefile.in b/Makefile.in
index aa68f4e..74601cc 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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 2cd1a37..ff2a30a 100644
--- 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
index 0000000..b98769f
--- /dev/null
+++ b/cgconfig.c
@@ -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;
+}
diff --git a/config.c b/config.c
index b0d4604..baaf7d8 100644
--- 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>
@@ -27,8 +30,10 @@
#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>
@@ -39,672 +44,417 @@
#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
index ffba8e8..0000000
--- a/file-ops.c
+++ /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;
-}
-
diff --git a/libcgroup-internal.h b/libcgroup-internal.h
index c2f2ce3..af5d396 100644
--- a/libcgroup-internal.h
+++ b/libcgroup-internal.h
@@ -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
diff --git a/libcgroup.h b/libcgroup.h
index 97c663d..9325846 100644
--- a/libcgroup.h
+++ b/libcgroup.h
@@ -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 cfc86c8..53141e9 100644
--- 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 $$;
}
diff --git a/samples/wlm.conf.3 b/samples/wlm.conf.3
index 6738624..a0e9a1b 100644
--- a/samples/wlm.conf.3
+++ b/samples/wlm.conf.3
@@ -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;
}