Hi Mahesh, On Wed, 18 May 2011 01:34:15 +0530 Mahesh J Salgaonkar <mahesh at linux.vnet.ibm.com> wrote: > > This patch enables to makedumpfile to read and process filter commands from > specified config file. It builds a list of filter info consisting of memory > address (paddr) and size to be filtered out. This list is used during > read_pfn() function to filter out user specified kernel data from vmcore > before writing it to compressed DUMPFILE. The filtered memory locations are > filled with 'X' (0x58) character. > > The filter command syntax is: > erase <Symbol>[.member[...]] [size <SizeValue>[K|M]] > erase <Symbol>[.member[...]] [size <SizeSymbol>] > erase <Symbol>[.member[...]] [nullify] > > Below are the examples how filter commands in config file look like: > > erase modules > erase cred_jar.name size 10 > erase vmlist.addr nullify Thank you for the work. I tested this feature by the above example, and confirmed the feature works fine. Nice work :-) There are some comments in the below lines. Can you check them ? > +/* > + * Read the non-terminal's which are in the form of <Symbol>[.member[...]] > + */ > +struct config_entry * > +create_config_entry(const char *token, unsigned short flag, int line) > +{ > + struct config_entry *ce = NULL, *ptr, *prev_ce; > + char *str, *cur, *next; > + long len; > + int depth = 0; > + > + if (!token) > + return NULL; > + > + cur = str = strdup(token); > + prev_ce = ptr = NULL; > + while (cur != NULL) { > + if ((next = strchr(cur, '.')) != NULL) { > + *next++ = '\0'; > + } > + if (!strlen(cur)) { > + cur = next; > + continue; > + } > + > + if ((ptr = calloc(1, sizeof(struct config_entry))) == NULL) { > + ERRMSG("Can't allocate memory for config_entry\n"); > + goto err_out; > + } > + ptr->line = line; > + ptr->flag |= flag; > + if (depth == 0) { > + /* First node is always a symbol name */ > + ptr->flag |= SYMBOL_ENTRY; > + } > + if (flag & FILTER_ENTRY) { > + ptr->name = strdup(cur); > + } > + if (flag & SIZE_ENTRY) { > + char ch = '\0'; > + int n = 0; > + /* See if absolute length is provided */ > + if ((depth == 0) && > + ((n = sscanf(cur, "%zd%c", &len, &ch)) > 0)) { > + if (len < 0) { > + ERRMSG("Config error at %d: size " > + "value must be positive.\n", > + line); > + goto err_out; > + } > + ptr->size = len; > + ptr->flag |= ENTRY_RESOLVED; > + if (n == 2) { > + /* Handle suffix. > + * K = Kilobytes > + * M = Megabytes > + */ > + switch (ch) { > + case 'M': > + case 'm': > + ptr->size *= 1024; > + case 'K': > + case 'k': > + ptr->size *= 1024; > + break; > + } > + } > + } > + else > + ptr->name = strdup(cur); > + } > + if (prev_ce) { > + prev_ce->next = ptr; > + prev_ce = ptr; > + } > + else > + ce = prev_ce = ptr; > + cur = next; > + depth++; > + ptr = NULL; > + } > + free(str); > + return ce; > + > +err_out: > + if (ce) > + free_config_entry(ce); > + if (ptr) > + free_config_entry(ptr); "free(str);" is necessary. > + return NULL; > +} [..] > +/* > + * read filter config file and return each string token. If the parameter > + * expected_token is non-NULL, then return the current token if it matches > + * with expected_token otherwise save the current token and return NULL. > + * At start of every module section filter_config.new_section is set to 1 and > + * subsequent function invocations return NULL untill filter_config.new_section > + * is reset to 0 by passing @flag = CONFIG_NEW_CMD (0x02). > + * > + * Parameters: > + * @expected_token INPUT > + * Token string to match with currnet token. > + * =NULL - return the current available token. > + * > + * @flag INPUT > + * =0x01 - Skip to next module section. > + * =0x02 - Treat the next token as next filter command and reset. > + * > + * @line OUTPUT > + * Line number of current token in filter config file. > + * > + * @cur_mod OUTPUT > + * Points to current module section name on non-NULL return value. > + * > + * @eof OUTPUT > + * set to -1 when end of file is reached. > + * set to -2 when end of section is reached. > + */ > +static char * > +get_config_token(char *expected_token, unsigned char flag, int *line, > + char **cur_mod, int *eof) > +{ > + char *p; > + struct filter_config *fc = &filter_config; > + int skip = flag & CONFIG_SKIP_SECTION; CONFIG_SKIP_SECTION is used only here, and we need to fix get_config() for the readability. Please check my comment in get_config(). [..] > +/* > + * Configuration file 'makedumpfile.conf' contains filter commands. > + * Every individual filter command is considered as a config entry. A config > + * entry can be provided on a single line or multiple lines. > + */ > +struct config * > +get_config(int skip) > +{ > + struct config *config; > + char *token = NULL; > + static int line_count = 0; > + char *cur_module = NULL; > + int eof = 0; > + unsigned char flag = CONFIG_NEW_CMD | skip; We need to change the above: unsigned char flag = CONFIG_NEW_CMD; if (skip) flag |= CONFIG_SKIP_SECTION; > + > + if ((config = calloc(1, sizeof(struct config))) == NULL) > + return NULL; > + > + if (get_config_token("erase", flag, &line_count, &cur_module, &eof)) { > + if (cur_module) > + config->module_name = strdup(cur_module); > + > + if (!read_filter_entry(config, line_count)) > + goto err_out; > + } > + else { > + if (!eof) { > + token = get_config_token(NULL, 0, &line_count, > + NULL, NULL); > + ERRMSG("Config error at %d: Invalid token '%s'.\n", > + line_count, token); > + } > + goto err_out; > + } > + return config; > +err_out: > + if (config) > + free_config(config); > + return NULL; > +} BTW makedumpfile.c has become a large file which is bigger than 10KLine, and I will separate it to some files for the maintenance. Thanks Ken'ichi Ohmichi