As per the discussion on the mailing list, the daemon should have the ability to load both configuration files and configuration directories.
Provide this ability. TODO: 1. Move to a fts based walk as opposed to a readdir. 2. Decide whether a configuration file is default or a configuration directory. 3. Handle minor coding style issues. Signed-off-by: Dhaval Giani <dhaval.gi...@gmail.com> --- src/cgrules.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++- src/daemon/cgrulesengd.c | 28 +++++++++++++- src/libcgroup-internal.h | 1 3 files changed, 116 insertions(+), 3 deletions(-) Index: libcg/src/daemon/cgrulesengd.c =================================================================== --- libcg.orig/src/daemon/cgrulesengd.c +++ libcg/src/daemon/cgrulesengd.c @@ -960,7 +960,7 @@ int main(int argc, char *argv[]) struct group *gr; /* Command line arguments */ - const char *short_options = "hvqf:s::ndQu:g:c:"; + const char *short_options = "hvqf:s::ndQu:g:c:D:"; struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"verbose", no_argument, NULL, 'v'}, @@ -973,10 +973,12 @@ int main(int argc, char *argv[]) {"socket-user", required_argument, NULL, 'u'}, {"socket-group", required_argument, NULL, 'g'}, {"config-file", required_argument, NULL, 'c'}, + {"config-dir", required_argument, NULL, 'D'}, {NULL, 0, NULL, 0} }; cgrules_config_file = NULL; + cgrules_config_dir = NULL; /* Make sure the user is root. */ if (getuid() != 0) { @@ -1069,6 +1071,13 @@ int main(int argc, char *argv[]) goto finished; } break; + case 'D': /* --config-dir */ + cgrules_config_dir = strdup(optarg); + if (!cgrules_config_dir) { + ret = 4; + goto finished; + } + break; default: usage(stderr, ""); ret = 2; @@ -1076,7 +1085,22 @@ int main(int argc, char *argv[]) } } - if (!cgrules_config_file) { + /* + * Cannot have both config dir and config file set. + * This will confuse the implementation. So just mark such a + * configuration as invalid and fail. + */ + if (cgrules_config_file && cgrules_config_dir) { + fprintf(stderr, "Error: Both configuration directory and " \ + "configuration file are mentioned\n"); + goto finished; + } + + /* + * XX: TODO: Decide if config dir is the default or the config file is + * Current implementation just keeps the config file as default. + */ + if (!cgrules_config_file && !cgrules_config_dir) { cgrules_config_file = strdup(CGRULES_DEFAULT_CONFIG); if (!cgrules_config_file) { fprintf(stderr, "Failed to set the correct"\ Index: libcg/src/libcgroup-internal.h =================================================================== --- libcg.orig/src/libcgroup-internal.h +++ libcg/src/libcgroup-internal.h @@ -68,6 +68,7 @@ __BEGIN_DECLS #define min(x,y) ((y)>(x)?(x):(y)) char *cgrules_config_file; +char *cgrules_config_dir; /* Check if cgroup_init has been called or not. */ int cgroup_initialized; Index: libcg/src/cgrules.c =================================================================== --- libcg.orig/src/cgrules.c +++ libcg/src/cgrules.c @@ -17,6 +17,8 @@ * */ +#define _GNU_SOURCE + #include <dirent.h> #include <errno.h> #include <libcgroup.h> @@ -38,9 +40,11 @@ #include <assert.h> #include <linux/un.h> #include <grp.h> +#include <stddef.h> /* Check if the rules cache has been loaded or not. */ static bool cgroup_rules_loaded; +static bool cgrules_dir_provided; /* List of configuration rules */ static struct cgroup_rule_list rl; @@ -474,8 +478,92 @@ unlock: static int cgroup_parse_rules(bool cache, uid_t muid, gid_t mgid, const char *mprocname) { - return cgroup_parse_rules_file(cache, muid, mgid, mprocname, cgrules_config_file); + DIR *cgrules_dir; + struct dirent *curr_ent = NULL; + int len; + struct dirent *dir_buff; + int read_ret; + int parse_fail_count = 0; + char *parse_fail_list = NULL; + + if (cgrules_config_file) + return cgroup_parse_rules_file(cache, muid, mgid, mprocname, + cgrules_config_file); + + /* + * This means we have a directory defined, and we parse using that + * TODO: Implement using fts if folks think that is a better option + */ + + cgrules_dir = opendir(cgrules_config_dir); + if (!cgrules_dir) { + last_errno = errno; + return ECGOTHER; + } + + len = offsetof(struct dirent, d_name) + + pathconf(cgrules_config_dir, _PC_NAME_MAX) + 1; + + dir_buff = malloc(len); + if (!dir_buff) { + last_errno = errno; + return ECGOTHER; + } + + read_ret = readdir_r(cgrules_dir, curr_ent, &dir_buff); + + while(read_ret == 0 && curr_ent) { + char *cgrules_file; + int parse_ret; + + /* + * We need a better way to handle DT_UNKNOWN, but for now we + * just pray to $DEITY that we can handle it :-) + */ + + if (curr_ent->d_type != DT_REG || curr_ent->d_type != DT_UNKNOWN) { + read_ret = readdir_r(cgrules_dir, curr_ent, &dir_buff); + continue; + } + + cgrules_file = strdup(curr_ent->d_name); + + parse_ret = cgroup_parse_rules_file(cache, muid, mgid, mprocname, + cgrules_file); + + if (parse_ret) { + char *tmp_list; + parse_fail_count++; + if (parse_fail_list) { + tmp_list = strdup(parse_fail_list); + if (!tmp_list) { + last_errno = errno; + return ECGOTHER; + } + + free(parse_fail_list); + asprintf(&parse_fail_list, "%s, %s", tmp_list, curr_ent->d_name); + } else { + parse_fail_list = strdup(curr_ent->d_name); + } + + } + read_ret = readdir_r(cgrules_dir, curr_ent, &dir_buff); + + } + fprintf(stderr, "Failed to parse %d files\n", parse_fail_count); + fprintf(stderr, "Failed to parse %s\n", parse_fail_list); + + /* + * TODO: Right return value + */ + if (parse_fail_count) + return 0; + + return 0; + } + /** cg_prepare_cgroup * Process the selected rule. Prepare the cgroup structure which can be * used to add the task to destination cgroup. ------------------------------------------------------------------------------ The modern datacenter depends on network connectivity to access resources and provide services. The best practices for maximizing a physical server's connectivity to a physical network are well understood - see how these rules translate into the virtual world? http://p.sf.net/sfu/oracle-sfdevnlfb _______________________________________________ Libcg-devel mailing list Libcg-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libcg-devel