diff options
Diffstat (limited to 'lib/dynamic_debug.c')
| -rw-r--r-- | lib/dynamic_debug.c | 73 | 
1 files changed, 58 insertions, 15 deletions
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 93fc5d500cd..310c753cf83 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -124,13 +124,13 @@ do {									\  } while (0)  /* - * Search the tables for _ddebug's which match the given - * `query' and apply the `flags' and `mask' to them.  Tells - * the user which ddebug's were changed, or whether none - * were matched. + * Search the tables for _ddebug's which match the given `query' and + * apply the `flags' and `mask' to them.  Returns number of matching + * callsites, normally the same as number of changes.  If verbose, + * logs the changes.  Takes ddebug_lock.   */ -static void ddebug_change(const struct ddebug_query *query, -			   unsigned int flags, unsigned int mask) +static int ddebug_change(const struct ddebug_query *query, +			unsigned int flags, unsigned int mask)  {  	int i;  	struct ddebug_table *dt; @@ -192,6 +192,8 @@ static void ddebug_change(const struct ddebug_query *query,  	if (!nfound && verbose)  		pr_info("no matches for query\n"); + +	return nfound;  }  /* @@ -449,7 +451,7 @@ static int ddebug_exec_query(char *query_string)  	unsigned int flags = 0, mask = 0;  	struct ddebug_query query;  #define MAXWORDS 9 -	int nwords; +	int nwords, nfound;  	char *words[MAXWORDS];  	nwords = ddebug_tokenize(query_string, words, MAXWORDS); @@ -461,8 +463,47 @@ static int ddebug_exec_query(char *query_string)  		return -EINVAL;  	/* actually go and implement the change */ -	ddebug_change(&query, flags, mask); -	return 0; +	nfound = ddebug_change(&query, flags, mask); +	vpr_info_dq((&query), (nfound) ? "applied" : "no-match"); + +	return nfound; +} + +/* handle multiple queries in query string, continue on error, return +   last error or number of matching callsites.  Module name is either +   in param (for boot arg) or perhaps in query string. +*/ +static int ddebug_exec_queries(char *query) +{ +	char *split; +	int i, errs = 0, exitcode = 0, rc, nfound = 0; + +	for (i = 0; query; query = split) { +		split = strpbrk(query, ";\n"); +		if (split) +			*split++ = '\0'; + +		query = skip_spaces(query); +		if (!query || !*query || *query == '#') +			continue; + +		if (verbose) +			pr_info("query %d: \"%s\"\n", i, query); + +		rc = ddebug_exec_query(query); +		if (rc < 0) { +			errs++; +			exitcode = rc; +		} else +			nfound += rc; +		i++; +	} +	pr_info("processed %d queries, with %d matches, %d errs\n", +		 i, nfound, errs); + +	if (exitcode) +		return exitcode; +	return nfound;  }  #define PREFIX_SIZE 64 @@ -615,9 +656,9 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,  	if (verbose)  		pr_info("read %d bytes from userspace\n", (int)len); -	ret = ddebug_exec_query(tmpbuf); +	ret = ddebug_exec_queries(tmpbuf);  	kfree(tmpbuf); -	if (ret) +	if (ret < 0)  		return ret;  	*offp += len; @@ -927,13 +968,15 @@ static int __init dynamic_debug_init(void)  	/* ddebug_query boot param got passed -> set it up */  	if (ddebug_setup_string[0] != '\0') { -		ret = ddebug_exec_query(ddebug_setup_string); -		if (ret) +		ret = ddebug_exec_queries(ddebug_setup_string); +		if (ret < 0)  			pr_warn("Invalid ddebug boot param %s",  				ddebug_setup_string);  		else -			pr_info("ddebug initialized with string %s", -				ddebug_setup_string); +			pr_info("%d changes by ddebug_query\n", ret); + +		/* keep tables even on ddebug_query parse error */ +		ret = 0;  	}  out_free:  |