----- Original Message ----- > From: "Jan Chaloupka" <jchal...@redhat.com> > To: libcg-devel@lists.sourceforge.net > Cc: jchal...@redhat.com, varek...@redhat.com > Sent: Thursday, July 24, 2014 8:20:51 AM > Subject: [PATCH 1/2] api.c: Adding support for loading configuration files > from cgrules.d directory > > Implementation of loading rules from /etc/cgrules.d/. Explanation is in the > cover letter. New function cgroup_parse_rules_file created, > calling cgroup_parse_rules. cgroup_parse_rules is invoked only in > cgroup_change_cgroup_flags, cgroup_init_rules_cache and > cgroup_reload_cached_rules functions. For them the change in > cgroup_parse_rules > implementation is transpart. > > Tested with two configuration files in /etc/cgrules.d/ and all rules > in /etc/cgrules.conf commented out: > > $ cat /etc/cgrules.conf > #*:ls cpu strom/%u > #*:sleep memory les/%g > > $ cat /etc/cgrules.d/cgrules1.conf > *:ls cpu strom/%u > > $ cat /etc/cgrules.d/cgrules2.conf > *:sleep memory les/%g > > plus cgconfig.[c|d/*] files: > $ cat /etc/cgconfig.conf > mount { > cpuset = /cgroup/cpuset; > cpu = /cgroup/cpu; > cpuacct = /cgroup/cpuacct; > memory = /cgroup/memory; > devices = /cgroup/devices; > freezer = /cgroup/freezer; > net_cls = /cgroup/net_cls; > blkio = /cgroup/blkio; > } > > $ cat /etc/cgconfig.d/small.conf > template strom/%u { > cpu {} > } > > group vetev { > cpu {} > } > > $ cat /etc/cgconfig.d/medium.conf > template les/%g { > memory {} > } > > group drevo/listi { > memory {} > } > > Tested to cache reload as well by sending SIGUSR2 signal to running > cgrulesengd process. After first reload I commented out all rules => no > rules match after invoking ls command. After second reload I uncommented > out ls rule => rule match after invoking ls command. After third reload > I uncommented out ls and sleep rule => debug output of cgrulesengd shows > both rules loaded in the cache > > Changelog: > * CGROUP_PARSE_STATE_UNLOCK removed > * reformulation of comment to "Cannot read directory. However, > CGRULES_CONF_FILE is succesfully parsed. Thus return as a success for > back compatibility." > * errno = 0 removed, once it is not zero, function returns, so need to set > it to 0 in every iteration > * fprintf replaced by cgroup_err > * added missing unlocks + new label unlock_list for all returns > > This > - * finds a rule matching the given UID or GID. It will store this rule in > rl, > + * finds a rule matching the given UID or GID. It will store this rule in > trl, > is valid correction. "It will store this rule in rl" talks about cache being > disabled. In this case, it is stored into trl. > > Signed-off-by: Jan Chaloupka <jchal...@redhat.com> Acked-by: Ivana Hutarova Varekova <varek...@redhat.com> > --- > src/api.c | 159 > +++++++++++++++++++++++++++++++++++++++++++--- > src/libcgroup-internal.h | 1 > 2 files changed, 148 insertions(+), 12 deletions(-) > > diff --git a/src/api.c b/src/api.c > index 0b3d8a0..5751b8f 100644 > --- a/src/api.c > +++ b/src/api.c > @@ -473,17 +473,19 @@ static char *cg_skip_unused_charactors_in_rule(char > *rule) > * The cache parameter alters the behavior of this function. If true, this > * function will read the entire configuration file and store the results in > * rl (global rules list). If false, this function will only parse until it > - * finds a rule matching the given UID or GID. It will store this rule in > rl, > + * finds a rule matching the given UID or GID. It will store this rule in > trl, > * as well as any children rules (rules that begin with a %) that it has. > * > * This function is NOT thread safe! > + * @param filename configuration file to parse > * @param cache True to cache rules, else false > * @param muid If cache is false, the UID to match against > * @param mgid If cache is false, the GID to match against > * @return 0 on success, -1 if no cache and match found, > 0 on error. > * TODO: Make this function thread safe! > + * > */ > -static int cgroup_parse_rules(bool cache, uid_t muid, > +static int cgroup_parse_rules_file(char *filename, bool cache, uid_t muid, > gid_t mgid, const char *mprocname) > { > /* File descriptor for the configuration file */ > @@ -544,21 +546,19 @@ static int cgroup_parse_rules(bool cache, uid_t muid, > else > lst = &trl; > > - /* If our list already exists, clean it. */ > - if (lst->head) > - cgroup_free_rule_list(lst); > - > /* Open the configuration file. */ > - pthread_rwlock_wrlock(&rl_lock); > - fp = fopen(CGRULES_CONF_FILE, "re"); > + fp = fopen(filename, "re"); > if (!fp) { > cgroup_warn("Warning: failed to open configuration file %s: > %s\n", > - CGRULES_CONF_FILE, strerror(errno)); > - goto unlock; > + filename, strerror(errno)); > + > + ret = ECGRULESPARSEFAIL; /* originally ret = 0, but */ > + /* this is parse fail, not success */ > + goto finish; > } > > /* Now, parse the configuration file one line at a time. */ > - cgroup_dbg("Parsing configuration file.\n"); > + cgroup_dbg("Parsing configuration file %s.\n", filename); > while (fgets(buff, sizeof(buff), fp) != NULL) { > linenum++; > > @@ -804,8 +804,143 @@ parsefail: > > close: > fclose(fp); > -unlock: > +finish: > + return ret; > +} > + > +/** > + * Parse CGRULES_CONF_FILE and all files in CGRULES_CONF_FILE_DIR. > + * If CGRULES_CONF_FILE_DIR does not exists or can not be read, > + * parse only CGRULES_CONF_FILE. This way we keep the back compatibility. > + * > + * Original description of this function moved to cgroup_parse_rules_file. > + * Also cloned and all occurences of file changed to files. > + * > + * Parse the configuration files that maps UID/GIDs to cgroups. If ever the > + * configuration files are modified, applications should call this function > to > + * load the new configuration rules. The function caller is responsible for > + * calling free() on each rule in the list. > + * > + * The cache parameter alters the behavior of this function. If true, this > + * function will read the entire content of all configuration files and > store > + * the results in rl (global rules list). If false, this function will only > + * parse until it finds a file and a rule matching the given UID or GID. > + * The remaining files are skipped. It will store this rule in trl, > + * as well as any children rules (rules that begin with a %) that it has. > + * > + * Files can be read in an random order so the first match must not be > + * dependent on it. Thus construct the rules the way not to break > + * this assumption. > + * > + * This function is NOT thread safe! > + * @param cache True to cache rules, else false > + * @param muid If cache is false, the UID to match against > + * @param mgid If cache is false, the GID to match against > + * @return 0 on success, -1 if no cache and match found, > 0 on error. > + * TODO: Make this function thread safe! > + */ > +static int cgroup_parse_rules(bool cache, uid_t muid, > + gid_t mgid, const char *mprocname) > +{ > + int ret; > + > + /* Pointer to the list that we're using */ > + struct cgroup_rule_list *lst = NULL; > + > + /* Directory variables */ > + DIR *d; > + struct dirent *item; > + const char *dirname = CGRULES_CONF_DIR; > + char *tmp; > + int sret; > + > + /* Determine which list we're using. */ > + if (cache) > + lst = &rl; > + else > + lst = &trl; > + > + /* If our list already exists, clean it. */ > + if (lst->head) > + cgroup_free_rule_list(lst); > + > + pthread_rwlock_wrlock(&rl_lock); > + > + /* Parse CGRULES_CONF_FILE configuration file (back compatibility). */ > + ret = cgroup_parse_rules_file(CGRULES_CONF_FILE, > + cache, muid, mgid, mprocname); > + > + /* > + * if match (ret = -1), stop parsing other files, just return > + * or ret > 0 => error > + */ > + if (ret != 0) { > + pthread_rwlock_unlock(&rl_lock); > + return ret; > + } > + > + /* Continue parsing */ > + d = opendir(dirname); > + if (!d) { > + cgroup_warn("Warning: Failed to open directory %s: %s\n", > + dirname, strerror(errno)); > + > + /* > + * Cannot read directory. However, CGRULES_CONF_FILE is > + * succesfully parsed. Thus return as a success > + * for back compatibility. > + */ > + pthread_rwlock_unlock(&rl_lock); > + > + return 0; > + } > + > + /* read all files from CGRULES_CONF_FILE_DIR */ > + do { > + item = readdir(d); > + if (item && (item->d_type == DT_REG > + || item->d_type == DT_LNK)) { > + > + sret = asprintf(&tmp, "%s/%s", dirname, item->d_name); > + if (sret < 0) { > + cgroup_err("Out of memory\n"); > + > + /* > + * Cannot read directory. However, > CGRULES_CONF_FILE is > + * succesfully parsed. Thus return as a success > + * for back compatibility. > + */ > + ret = 0; > + goto unlock_list; > + } > + > + cgroup_dbg("Parsing cgrules file: %s\n", tmp); > + ret = cgroup_parse_rules_file(tmp, > + cache, muid, mgid, mprocname); > + > + free(tmp); > + > + /* match with cache disabled? */ > + if (ret != 0) > + goto unlock_list; > + } > + if (!item && errno) { > + cgroup_warn("Warning: cannot read %s: %s\n", > + dirname, strerror(errno)); > + /* > + * Cannot read an item. But continue for > + * back compatibility as a success. > + */ > + ret = 0; > + goto unlock_list; > + } > + } while (item != NULL); > + > +unlock_list: > + closedir(d); > + > pthread_rwlock_unlock(&rl_lock); > + > return ret; > } > > diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h > index c128788..9875dd9 100644 > --- a/src/libcgroup-internal.h > +++ b/src/libcgroup-internal.h > @@ -53,6 +53,7 @@ __BEGIN_DECLS > #define CGCONFIG_CONF_DIR "/etc/cgconfig.d" > > #define CGRULES_CONF_FILE "/etc/cgrules.conf" > +#define CGRULES_CONF_DIR "/etc/cgrules.d" > #define CGRULES_MAX_FIELDS_PER_LINE 3 > > #define CGROUP_BUFFER_LEN (5 * FILENAME_MAX) > >
------------------------------------------------------------------------------ Infragistics Professional Build stunning WinForms apps today! Reboot your WinForms applications with our WinForms controls. Build a bridge from your legacy apps to the future. http://pubads.g.doubleclick.net/gampad/clk?id=153845071&iu=/4140/ostg.clktrk _______________________________________________ Libcg-devel mailing list Libcg-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libcg-devel