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)
downloadlibcg-d1ab753ba5d0d641b52cb90e00ce2eabfae476f4.tar.gz
libcg-d1ab753ba5d0d641b52cb90e00ce2eabfae476f4.tar.xz
libcg-d1ab753ba5d0d641b52cb90e00ce2eabfae476f4.zip
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;
}