diff options
author | Balbir Singh <balbir@linux.vnet.ibm.com> | 2008-04-10 12:13:23 +0000 |
---|---|---|
committer | Balbir Singh <balbir@linux.vnet.ibm.com> | 2008-04-10 12:13:23 +0000 |
commit | e2bd008f062988edb7ddef0a6070c7a6c38c3cee (patch) | |
tree | 86adef3313f8238228cb0acec99f100a138f5adb | |
parent | 0b2fec2a92a3e3ef1c1e15ba71c3945674a01487 (diff) | |
download | libcg-e2bd008f062988edb7ddef0a6070c7a6c38c3cee.tar.gz libcg-e2bd008f062988edb7ddef0a6070c7a6c38c3cee.tar.xz libcg-e2bd008f062988edb7ddef0a6070c7a6c38c3cee.zip |
Removed balbir
Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
git-svn-id: https://libcg.svn.sourceforge.net/svnroot/libcg/trunk@11 4f4bb910-9a46-0410-90c8-c897d4f1cd53
-rw-r--r-- | balbir/Makefile | 44 | ||||
-rw-r--r-- | balbir/api.c | 325 | ||||
-rw-r--r-- | balbir/config.c | 704 | ||||
-rw-r--r-- | balbir/file-ops.c | 176 | ||||
-rw-r--r-- | balbir/lex.l | 33 | ||||
-rw-r--r-- | balbir/libcg.h | 173 | ||||
-rw-r--r-- | balbir/parse.y | 257 | ||||
-rw-r--r-- | balbir/samples/wlm.conf | 35 | ||||
-rw-r--r-- | balbir/samples/wlm.conf.2 | 40 | ||||
-rw-r--r-- | balbir/samples/wlm.conf.3 | 65 |
10 files changed, 0 insertions, 1852 deletions
diff --git a/balbir/Makefile b/balbir/Makefile deleted file mode 100644 index 9c175fa..0000000 --- a/balbir/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright IBM Corporation. 2007 -# -# Authors: 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. -# -YACC_DEBUG=-t -DEBUG=-DDEBUG -INC=-I. -CFLAGS=-g -O2 -Wextra $(DEBUG) $(INC) -LIBS= -lcg -LDFLAGS= -L . -INSTALLPREFIX= - -all: cgconfig libcg.so - -cgconfig: libcg.so config.c y.tab.c lex.yy.c libcg.h file-ops.c - $(CC) $(CFLAGS) -o $@ y.tab.c lex.yy.c config.c file-ops.c $(LDFLAGS) $(LIBS) - -y.tab.c: parse.y lex.yy.c - byacc -v -d parse.y - -lex.yy.c: lex.l - flex lex.l - -libcg.so: api.c libcg.h - $(CXX) $(CFLAGS) -shared -fPIC -o $@ api.c - -install: libcg.so - \cp libcg.h $(INSTALLPREFIX)/usr/include - \cp libcg.so $(INSTALLPREFIX)/usr/lib - -uninstall: libcg.so - \rm $(INSTALLPREFIX)/usr/include/libcg.h - \rm $(INSTALLPREFIX)/usr/lib/libcg.so - -clean: - \rm -f y.tab.c y.tab.h lex.yy.c y.output cgconfig libcg.so diff --git a/balbir/api.c b/balbir/api.c deleted file mode 100644 index df594ea..0000000 --- a/balbir/api.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright IBM Corporation. 2007 - * - * Author: 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. - * - * TODOs: - * 1. Convert comments to Docbook style. - * 2. Add more APIs for the control groups. - * 3. Handle the configuration related APIs. - * 4. Error handling. - * - * Code initiated and designed by Dhaval Giani. All faults are most likely - * his mistake. - */ - -#include <errno.h> -#include <libcg.h> -#include <mntent.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/syscall.h> -#include <unistd.h> - -static char MOUNT_POINT[FILENAME_MAX]; - -int cg_init() -{ - FILE *proc_mount; - struct mntent *ent; - - proc_mount = fopen("/proc/mounts", "r"); - ent = getmntent(proc_mount); - - while (strcmp(ent->mnt_fsname,"cgroup") != 0) { - ent = getmntent(proc_mount); - if (ent == NULL) - return ECGROUPNOTMOUNTED; - } - strcpy(MOUNT_POINT, ent->mnt_dir); - fclose(proc_mount); - return 0; -} - -static int cg_test_mounted_fs() -{ - FILE *proc_mount; - struct mntent *ent; - - proc_mount = fopen("/proc/mounts", "r"); - if (proc_mount == NULL) { - return -1; - } - ent = getmntent(proc_mount); - - while (strcmp(ent->mnt_fsname, "cgroup") !=0) { - ent = getmntent(proc_mount); - if (ent == NULL) - return 0; - } - fclose(proc_mount); - return 1; -} - -static inline pid_t cg_gettid() -{ - return syscall(__NR_gettid); -} - -static char* cg_build_path(char *name, char *path) -{ - strcpy(path, MOUNT_POINT); - strcat(path, name); - strcat(path, "/"); - return path; -} - -/** cg_attach_task_pid is used to assign tasks to a cgroup. - * struct cgroup *cgroup: The cgroup to assign the thread to. - * pid_t tid: The thread to be assigned to the cgroup. - * - * returns 0 on success. - * returns ECGROUPNOTOWNER if the caller does not have access to the cgroup. - * returns ECGROUPNOTALLOWED for other causes of failure. - */ -int cg_attach_task_pid(struct cgroup *cgroup, pid_t tid) -{ - char path[FILENAME_MAX]; - FILE *tasks; - - if (cgroup == NULL) - strcpy(path, MOUNT_POINT); - else { - cg_build_path(cgroup->name, path); - } - - strcat(path, "/tasks"); - - tasks = fopen(path, "w"); - if (!tasks) { - switch (errno) { - case EPERM: - return ECGROUPNOTOWNER; - default: - return ECGROUPNOTALLOWED; - } - } - fprintf(tasks, "%d", tid); - fclose(tasks); - - return 0; - -} - -/** cg_attach_task is used to attach the current thread to a cgroup. - * struct cgroup *cgroup: The cgroup to assign the current thread to. - * - * See cg_attach_task_pid for return values. - */ -int cg_attach_task(struct cgroup *cgroup) -{ - pid_t tid = cg_gettid(); - int error; - - error = cg_attach_task_pid(cgroup, tid); - - return error; -} - -/* - * create_control_group() - * This is the basic function used to create the control group. This function - * just makes the group. It does not set any permissions, or any control values. - * The argument path is the fully qualified path name to make it generic. - */ -static int cg_create_control_group(char *path) -{ - int error; - if (!cg_test_mounted_fs()) - return ECGROUPNOTMOUNTED; - error = mkdir(path, 0700); - if (!error) { - switch(errno) { - case EPERM: - return ECGROUPNOTOWNER; - default: - return ECGROUPNOTALLOWED; - } - } - return error; -} - -/* - * set_control_value() - * This is the low level function for putting in a value in a control file. - * This function takes in the complete path and sets the value in val in that - * file. - * - * TODO: - * At this point I am not sure what all values the control file can take. So - * I put in an int arg. But this has to be made much more robust. - */ -static int cg_set_control_value(char *path, char *val) -{ - int error; - FILE *control_file; - if (!cg_test_mounted_fs()) - return ECGROUPNOTMOUNTED; - - control_file = fopen(path, "a"); - - if (!control_file) { - if (errno == EPERM) { - /* - * We need to set the correct error value, does the - * group exist but we don't have the subsystem - * mounted at that point, or is it that the group - * does not exist. So we check if the tasks file - * exist. Before that, we need to extract the path. - */ - int len = strlen(path); - - while (*(path+len) != '/') - len--; - *(path+len+1) = '\0'; - strcat(path, "tasks"); - control_file = fopen(path, "r"); - if (!control_file) { - if (errno == ENOENT) - return ECGROUPSUBSYSNOTMOUNTED; - } - fclose(control_file); - return ECGROUPNOTALLOWED; - } - } - - fprintf(control_file, "%s", val); - fclose(control_file); - return 0; -} - -/** cg_modify_cgroup modifies the cgroup control files. - * struct cgroup *cgroup: The name will be the cgroup to be modified. - * The values will be the values to be modified, those not mentioned - * in the structure will not be modified. - * - * The uids cannot be modified yet. - * - * returns 0 on success. - * - */ - -int cg_modify_cgroup(struct cgroup *cgroup) -{ - char path[FILENAME_MAX], base[FILENAME_MAX]; - int i; - int error; - - cg_build_path(cgroup->name, base); - - for (i = 0; i < CG_CONTROLLER_MAX && cgroup->controller[i]; - i++, strcpy(path, base)) { - int j; - for(j = 0; j < CG_NV_MAX && - cgroup->controller[i]->values[j]; - j++, strcpy(path, base)) { - strcat(path, cgroup->controller[i]->values[j]->name); - error = cg_set_control_value(path, - cgroup->controller[i]->values[j]->value); - if (error) - goto err; - } - } - return 0; -err: - return error; - -} - -/** create_cgroup creates a new control group. - * struct cgroup *cgroup: The control group to be created - * - * returns 0 on success. - */ -int cg_create_cgroup(struct cgroup *cgroup) -{ - char path[FILENAME_MAX], base[FILENAME_MAX]; - int i; - int error; - - if (MOUNT_POINT == NULL) - return ECGROUPNOTMOUNTED; - - cg_build_path(cgroup->name, path); - - error = cg_create_control_group(path); - - strcpy(base, path); - - for (i = 0; i < CG_CONTROLLER_MAX && cgroup->controller[i]; - i++, strcpy(path, base)) { - int j; - for(j = 0; j < CG_NV_MAX && cgroup->controller[i]->values[j]; - j++, strcpy(path, base)) { - strcat(path, cgroup->controller[i]->values[j]->name); - error = cg_set_control_value(path, - cgroup->controller[i]->values[j]->value); - chown(path, cgroup->control_uid, cgroup->control_gid); - if (!error) - return error; - } - } - strcpy(path, base); - strcat(path, "tasks"); - chown(path, cgroup->tasks_uid, cgroup->tasks_gid); - return error; -} - -/** cg_delete cgroup deletes a control group. - * struct cgroup *cgroup takes the group which is to be deleted. - * - * returns 0 on success. - */ -int cg_delete_cgroup(struct cgroup *cgroup) -{ - FILE *delete_tasks, *base_tasks; - int tids; - char path[FILENAME_MAX]; - int error; - - strcpy(path, MOUNT_POINT); - strcat(path,"/tasks"); - - base_tasks = fopen(path, "w"); - - cg_build_path(cgroup->name, path); - strcat(path,"tasks"); - - delete_tasks = fopen(path, "r"); - - while (!feof(delete_tasks)) { - fscanf(delete_tasks, "%d", &tids); - fprintf(base_tasks, "%d", tids); - } - - cg_build_path(cgroup->name, path); - - error = rmdir(path); - - if (!error) { - return ECGROUPNOTALLOWED; - } - - return error; -} diff --git a/balbir/config.c b/balbir/config.c deleted file mode 100644 index 7b4b0f7..0000000 --- a/balbir/config.c +++ /dev/null @@ -1,704 +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. - * - * TODOs: - * 1. Implement our own hashing scheme - * 2. Add namespace support - * 3. Add support for parsing cgroup filesystem and creating a - * config out of it. - * - * Code initiated and designed by Balbir Singh. All faults are most likely - * his mistake. - */ - -#include <assert.h> -#include <dirent.h> -#include <errno.h> -#include <grp.h> -#include <libcg.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 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", - NULL, -}; - -/* - * File traversal routines require the maximum number of open file - * descriptors to be specified - */ -const int cg_max_openfd = 20; - -/* - * Insert the group into the list of group names we maintain. This helps - * us cleanup nicely - */ -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; - - if (!group_list) { - group_list = tmp; - return 1; - } - curr = group_list; - while (curr->next) - curr = curr->next; - - curr->next = tmp; - return 1; -} - -/* - * Cleanup the group list. We walk the group list and free the entries in the - * hash tables and controller specific entries. - */ -int cg_cleanup_group_list(void) -{ - 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); - } - - return 1; -} - -/* - * Find and walk the mount_table structures to find the specified controller - * name. This routine is *NOT* thread safe. - */ -struct mount_table *cg_find_mount_info(const char *controller_name) -{ - struct mount_table *curr = mount_table; - char *str; - - while (curr) { - str = curr->options; - if (!str) - return NULL; - - str = strtok(curr->options, ","); - do { - if (!strncmp(str, controller_name, strlen(str))) - return curr; - str = strtok(NULL, ","); - } while(str); - curr = curr->next; - } - return NULL; -} - -int cg_cpu_controller_settings(struct cg_group *cg_group, - const char *group_path) -{ - int ret = 1; - char *shares_file; - - shares_file = malloc(strlen(group_path) + strlen("/cpu.shares") + 1); - if (!shares_file) - return 0; - - strncpy(shares_file, group_path, strlen(group_path)); - shares_file = strncat(shares_file, "/cpu.shares", - strlen("/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; -} - -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 - assert(0); - return ret; -} - -int cg_create_group(struct cg_group *cg_group) -{ - int i, ret; - struct mount_table *mount_info; - char *group_path, *tasks_file, *shares_file; - - dbg("found group %s\n", cg_group->name); - - for (i = 0; cg_controller_names[i]; i++) { - - /* - * Find the mount point related information - */ - mount_info = cg_find_mount_info(cg_controller_names[i]); - dbg("mount_info for controller %s:%s\n", - mount_info->mount_point, cg_controller_names[i]); - if (!mount_info) - return 0; - - /* - * TODO: Namespace support is most likely going to be - * plugged in here - */ - - /* - * Find the path to the group directory - */ - group_path = cg_build_group_path(cg_group, mount_info); - if (!group_path) - 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; - - /* - * Find the tasks file, should probably be encapsulated - * like we encapsulate cg_build_group_path - */ - tasks_file = malloc(strlen(group_path) + strlen("/tasks") + 1); - if (!tasks_file) - goto cleanup_dir; - strncpy(tasks_file, group_path, strlen(group_path)); - 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); - free(tasks_file); - free(group_path); - } - return 1; -cleanup_perm: - rmdir(group_path); -cleanup_dir: - free(group_path); -cleanup_group: - return 0; -} - -/* - * Go ahead and create the groups in the filesystem. This routine will need - * to be revisited everytime new controllers are added. - */ -int cg_create_groups(void) -{ - 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; - } - - return ret; -} - -/* - * 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; - } - - return 1; -err: - free(group_path); - 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 - */ -struct cg_group *cg_get_current_group(void) -{ - if (!current_group) - current_group = calloc(1, sizeof(*current_group)); - - return current_group; -} - -/* - * 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; -} - -int cg_insert_group(const char *group_name) -{ - struct cg_group *cg_group = cg_get_current_group(); - ENTRY item, *found_item; - int ret; - - 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; - } - 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(); - return 1; -err: - cg_cleanup_group_list(); - 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. - */ -int cg_parse_controller_options(char *controller, char *name_value) -{ - struct cg_group *cg_group = cg_get_current_group(); - char *name, *value; - - if (!cg_group) - 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; - } - dbg("cpu name %s value %s\n", name, value); - } else { - return 0; - } - free(controller); - free(name_value); - return 1; -} - -/* - * Convert the uid/gid field and supplied value to appropriate task - * permissions. This routine is *NOT* thread safe. - */ -int cg_group_task_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->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; -} - -/* - * 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 - */ -int cg_init_group_and_mount_info(void) -{ - int ret; - - group_list = NULL; - mount_table = NULL; - current_group = NULL; - - ret = hcreate_r(MAX_GROUP_ELEMENTS, &group_hash); - if (!ret) - return 0; - return 1; -} - -/* - * 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. - */ -void cg_destroy_group_and_mount_info(void) -{ - hdestroy_r(&group_hash); - group_list = NULL; - mount_table = NULL; - current_group = NULL; -} - -/* - * Insert a name, mount_point pair into the mount_table data structure - * TODO: Validate names and mount points - */ -int cg_insert_into_mount_table(const char *name, const char *mount_point) -{ - 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; - } - - return 1; -} - -void cg_cleanup_mount_table(void) -{ - struct mount_table *curr = mount_table, *tmp; - - while (curr) { - tmp = curr; - curr = curr->next; - tmp->next = NULL; - - /* - * Some of this data might have been allocated by the lexer - * while parsing tokens - */ - free(tmp->mount_point); - free(tmp->options); - - free(tmp); - } -} - -int cg_load_config(const char *pathname) -{ - yyin = fopen(pathname, "rw"); - if (!yyin) { - dbg("Failed to open file %s\n", pathname); - return 0; - } - - if (!cg_init_group_and_mount_info()) - return 0; - - if (yyparse() != 0) { - dbg("Failed to parse file %s\n", pathname); - return 0; - } - - if (!cg_mount_controllers()) - goto err_mnt; - if (!cg_create_groups()) - goto err_grp; - - fclose(yyin); - return 1; -err_grp: - cg_destroy_groups(); - cg_cleanup_group_list(); -err_mnt: - cg_unmount_controllers(); - cg_cleanup_mount_table(); - 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; - } - } - - cg_destroy_group_and_mount_info(); -} diff --git a/balbir/file-ops.c b/balbir/file-ops.c deleted file mode 100644 index a627286..0000000 --- a/balbir/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 <libcg.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(const 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, const char *group_path) -{ - int ret; - ret = mkdir(group_path, 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_IROTH | S_IXOTH); - 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/balbir/lex.l b/balbir/lex.l deleted file mode 100644 index f9cc1ae..0000000 --- a/balbir/lex.l +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright IBM Corporation. 2007 - * - * Authors: 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. - */ - -%{ -#include "y.tab.h" -int line_no = 1; - -%} - -%% -\n {line_no++;} -[ \t] {/* DO NOTHING */} -^#.*[ \t]* {/* Comments */} -^\*.*[ \t]* {/* Comments */} -"mount" {return MOUNT;} -"task" {return TASK;} -"admin" {return ADMIN;} -"perm" {return PERM;} -"group" {return GROUP;} -[a-zA-Z0-9_\-\/\.]+ {yylval.name = strdup(yytext); return ID;} -. {return yytext[0];} -%% - diff --git a/balbir/libcg.h b/balbir/libcg.h deleted file mode 100644 index 3c4db67..0000000 --- a/balbir/libcg.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright IBM Corporation. 2007 - * - * Author: 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. - * - */ - -#ifndef _LIBCG_H -#define _LIBCG_H - -#include <features.h> - -__BEGIN_DECLS - -#include <grp.h> -#include <linux/types.h> -#include <stdio.h> -#include <sys/stat.h> - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#ifndef __USE_GNU -#define __USE_GNU -#endif - -/* Maximum number of mount points/controllers */ -#define MAX_MNT_ELEMENTS 8 -/* Estimated number of groups created */ -#define MAX_GROUP_ELEMENTS 128 - -int verbose; - -#ifdef DEBUG -#define dbg(x...) if (verbose) { \ - printf(x); \ - } -#else -#define dbg(x...) do { } while(0) -#endif - -/* - * NOTE: Wide characters are not supported at the moment. Wide character support - * 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 - */ -/* XX: Why a recursive structure? */ -struct list_of_names { - char *name; - struct list_of_names *next; -}; - -enum cg_msg_type { - CG_MSG_LOAD_FILE, - CG_MSG_UNLOAD_FILE, - CG_MSG_ERR, - CG_MSG_DONE, -}; - -enum cg_errors { - ECGROUPNOTCOMPILED=50000, - ECGROUPNOTMOUNTED, - ECGROUPNOTEXIST, - ECGROUPNOTCREATED, - ECGROUPSUBSYSNOTMOUNTED, - ECGROUPNOTOWNER, - ECGROUPNOTALLOWED, // This is the stock error. Default error. -}; - -#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, const 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 -/* Functions and structures that can be used by the application*/ -struct control_value { - char name[FILENAME_MAX]; - char *value; -}; - -struct controller { - char *name; - struct control_value *values[CG_NV_MAX]; -}; - -struct cgroup { - char *name; - struct controller *controller[CG_CONTROLLER_MAX]; - uid_t tasks_uid; - gid_t tasks_gid; - uid_t control_uid; - gid_t control_gid; -}; - -int cg_init(void); -int cg_attach_task(struct cgroup *cgroup); -int cg_modify_cgroup(struct cgroup *cgroup); -int cg_create_cgroup(struct cgroup *cgroup); -int cg_delete_cgroup(struct cgroup *cgroup); - -__END_DECLS - -#endif /* _LIBCG_H */ diff --git a/balbir/parse.y b/balbir/parse.y deleted file mode 100644 index fe7d5fe..0000000 --- a/balbir/parse.y +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright IBM Corporation. 2007 - * - * Authors: 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. - * - * NOTE: The grammar has been modified, not to be the most efficient, but - * to allow easy updation of internal data structures. - */ -%{ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <libcg.h> - -int yylex(void); -extern int line_no; -extern char *yytext; - -void yyerror(char *s) -{ - fprintf(stderr, "error at line number %d at %c:%s", line_no, *yytext, - s); -} - -int yywrap(void) -{ - return 1; -} - -%} - -%token ID MOUNT GROUP PERM TASK ADMIN - -%union { - char *name; - char chr; - int val; -} -%type <name> ID namevalue_conf -%type <val> mountvalue_conf mount task_namevalue_conf admin_namevalue_conf -%type <val> admin_conf task_conf task_or_admin group_conf group start -%start start -%% - -start : start group - { - $$ = $1; - } - | start mount - { - $$ = $1; - } - | - { - $$ = 1; - } - ; - -group : GROUP ID '{' group_conf '}' - { - $$ = $4; - if ($$) - cg_insert_group($2); - else { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - ; - -group_conf - : ID '{' namevalue_conf '}' - { - $$ = cg_parse_controller_options($1, $3); - if (!$$) { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - | group_conf ID '{' namevalue_conf '}' - { - $$ = cg_parse_controller_options($2, $4); - if (!$$) { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - | PERM '{' task_or_admin '}' - { - $$ = $3; - if (!$$) { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - ; - -namevalue_conf - : ID '=' ID ';' - { - $1 = realloc($1, strlen($1) + strlen($3) + 2); - $1 = strncat($1, " ", strlen(" ")); - $$ = strncat($1, $3, strlen($3)); - free($3); - } - | namevalue_conf ID '=' ID ';' - { - $2 = realloc($2, strlen($2) + strlen($4) + 2); - $2 = strncat($2, " ", strlen(" ")); - $$ = strncat($2, $4, strlen($4)); - free($4); - } - ; - -task_namevalue_conf - : ID '=' ID ';' - { - $$ = cg_group_task_perm($1, $3); - if (!$$) { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - | task_namevalue_conf ID '=' ID ';' - { - $$ = $1 && cg_group_task_perm($2, $4); - if (!$$) { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - ; - -admin_namevalue_conf - : ID '=' ID ';' - { - $$ = cg_group_admin_perm($1, $3); - if (!$$) { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - | admin_namevalue_conf ID '=' ID ';' - { - $$ = $1 && cg_group_admin_perm($2, $4); - if (!$$) { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - ; - -task_or_admin - : TASK '{' task_namevalue_conf '}' admin_conf - { - $$ = $3 && $5; - if (!$$) { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - | ADMIN '{' admin_namevalue_conf '}' task_conf - { - $$ = $3 && $5; - if (!$$) { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - ; - -admin_conf: ADMIN '{' admin_namevalue_conf '}' - { - $$ = $3; - if (!$$) { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - ; - -task_conf: TASK '{' task_namevalue_conf '}' - { - $$ = $3; - if (!$$) { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - ; - -mountvalue_conf - : ID '=' ID ';' - { - if (!cg_insert_into_mount_table($1, $3)) { - cg_cleanup_mount_table(); - $$ = 0; - return $$; - } - $$ = 1; - } - | mountvalue_conf ID '=' ID ';' - { - if (!cg_insert_into_mount_table($2, $4)) { - cg_cleanup_mount_table(); - $$ = 0; - return $$; - } - $$ = 1; - } - ; - -mount : MOUNT '{' mountvalue_conf '}' - { - $$ = $3; - if (!$$) { - fprintf(stderr, "parsing failed at line number %d\n", - line_no); - $$ = 0; - return $$; - } - } - ; - - -%% diff --git a/balbir/samples/wlm.conf b/balbir/samples/wlm.conf deleted file mode 100644 index dc905ad..0000000 --- a/balbir/samples/wlm.conf +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright IBM Corporation. 2007 -# -# Authors: 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. -# -# controller file -# - -group ca1 { - perm { - task { - uid = balbir; - gid = cgroup; - } - admin { - uid = root; - gid = cgroup; - } - } - - cpu { - cpu.shares = 500; - } -} - -mount { - cpu = /container; -} diff --git a/balbir/samples/wlm.conf.2 b/balbir/samples/wlm.conf.2 deleted file mode 100644 index e4739e0..0000000 --- a/balbir/samples/wlm.conf.2 +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright IBM Corporation. 2007 -# -# Authors: 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. -# -# controller file -# - -group ca1 { - perm { - task { - uid = bulls; - gid = bears; - } - admin { - uid = root; - gid = root; - } - } - - cpu { - cpu.shares = 500; - } - - memory { - memory.limit_in_bytes = 200M; - } -} - -mount { - cpu = /container; - memory = /memory; -} diff --git a/balbir/samples/wlm.conf.3 b/balbir/samples/wlm.conf.3 deleted file mode 100644 index 6738624..0000000 --- a/balbir/samples/wlm.conf.3 +++ /dev/null @@ -1,65 +0,0 @@ -# -# Copyright IBM Corporation. 2007 -# -# Authors: 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. -# -# controller file -# - -group ca1 { - perm { - task { - uid = root; - gid = kvm; - } - admin { - uid = root; - gid = root; - } - } - - cpu { - cpu.shares = 500; - } - - memory { - memory.limit_in_bytes = 200M; - } -} - -group default { - perm { - task { - uid = root; - gid = root; - } - admin { - uid = root; - gid = root; - } - } - - cpu { - cpu.shares = 500; - } - - memory { - memory.limit_in_bytes = 200M; - } -} - -mount { - cpu = /container; - memory = /memory; -} - -mount { - cpu_acct = /acct; -} |