dyndbg: validate class FOO by checking with module
[sfrench/cifs-2.6.git] / lib / dynamic_debug.c
index b71efd0b491dc46de047cf50ae86e1caf315c76d..db96ded78c3f1137fc55dc36c8064055621223ee 100644 (file)
@@ -56,6 +56,7 @@ struct ddebug_query {
        const char *module;
        const char *function;
        const char *format;
+       const char *class_string;
        unsigned int first_lineno, last_lineno;
 };
 
@@ -136,15 +137,33 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
                        fmtlen--;
        }
 
-       v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u\n",
-                msg,
-                query->function ?: "",
-                query->filename ?: "",
-                query->module ?: "",
-                fmtlen, query->format ?: "",
-                query->first_lineno, query->last_lineno);
+       v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%s\n",
+                 msg,
+                 query->function ?: "",
+                 query->filename ?: "",
+                 query->module ?: "",
+                 fmtlen, query->format ?: "",
+                 query->first_lineno, query->last_lineno, query->class_string);
 }
 
+static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table const *dt,
+                                                         const char *class_string, int *class_id)
+{
+       struct ddebug_class_map *map;
+       int idx;
+
+       list_for_each_entry(map, &dt->maps, link) {
+               idx = match_string(map->class_names, map->length, class_string);
+               if (idx >= 0) {
+                       *class_id = idx + map->base;
+                       return map;
+               }
+       }
+       *class_id = -ENOENT;
+       return NULL;
+}
+
+#define __outvar /* filled by callee */
 /*
  * Search the tables for _ddebug's which match the given `query' and
  * apply the `flags' and `mask' to them.  Returns number of matching
@@ -159,6 +178,8 @@ static int ddebug_change(const struct ddebug_query *query,
        unsigned int newflags;
        unsigned int nfound = 0;
        struct flagsbuf fbuf, nbuf;
+       struct ddebug_class_map *map = NULL;
+       int __outvar valid_class;
 
        /* search for matching ddebugs */
        mutex_lock(&ddebug_lock);
@@ -169,9 +190,22 @@ static int ddebug_change(const struct ddebug_query *query,
                    !match_wildcard(query->module, dt->mod_name))
                        continue;
 
+               if (query->class_string) {
+                       map = ddebug_find_valid_class(dt, query->class_string, &valid_class);
+                       if (!map)
+                               continue;
+               } else {
+                       /* constrain query, do not touch class'd callsites */
+                       valid_class = _DPRINTK_CLASS_DFLT;
+               }
+
                for (i = 0; i < dt->num_ddebugs; i++) {
                        struct _ddebug *dp = &dt->ddebugs[i];
 
+                       /* match site against query-class */
+                       if (dp->class_id != valid_class)
+                               continue;
+
                        /* match against the source filename */
                        if (query->filename &&
                            !match_wildcard(query->filename, dp->filename) &&
@@ -420,6 +454,8 @@ static int ddebug_parse_query(char *words[], int nwords,
                } else if (!strcmp(keyword, "line")) {
                        if (parse_linerange(query, arg))
                                return -EINVAL;
+               } else if (!strcmp(keyword, "class")) {
+                       rc = check_set(&query->class_string, arg, "class");
                } else {
                        pr_err("unknown keyword \"%s\"\n", keyword);
                        return -EINVAL;
@@ -854,6 +890,20 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
        return dp;
 }
 
+#define class_in_range(class_id, map)                                  \
+       (class_id >= map->base && class_id < map->base + map->length)
+
+static const char *ddebug_class_name(struct ddebug_iter *iter, struct _ddebug *dp)
+{
+       struct ddebug_class_map *map;
+
+       list_for_each_entry(map, &iter->table->maps, link)
+               if (class_in_range(dp->class_id, map))
+                       return map->class_names[dp->class_id - map->base];
+
+       return NULL;
+}
+
 /*
  * Seq_ops show method.  Called several times within a read()
  * call from userspace, with ddebug_lock held.  Formats the
@@ -865,6 +915,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
        struct ddebug_iter *iter = m->private;
        struct _ddebug *dp = p;
        struct flagsbuf flags;
+       char const *class;
 
        if (p == SEQ_START_TOKEN) {
                seq_puts(m,
@@ -877,7 +928,16 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
                   iter->table->mod_name, dp->function,
                   ddebug_describe_flags(dp->flags, &flags));
        seq_escape_str(m, dp->format, ESCAPE_SPACE, "\t\r\n\"");
-       seq_puts(m, "\"\n");
+       seq_puts(m, "\"");
+
+       if (dp->class_id != _DPRINTK_CLASS_DFLT) {
+               class = ddebug_class_name(iter, dp);
+               if (class)
+                       seq_printf(m, " class:%s", class);
+               else
+                       seq_printf(m, " class unknown, _id:%d", dp->class_id);
+       }
+       seq_puts(m, "\n");
 
        return 0;
 }