[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH 29/30] dyndbg: Convert to code tagging



From: Kent Overstreet <kent.overstreet@xxxxxxxxx>

This converts dynamic debug to the new code tagging framework, which
provides an interface for iterating over objects in a particular elf
section.

It also converts the debugfs interface from seq_file to the style used
by other code tagging users, which also makes the code a bit smaller and
simpler.

It doesn't yet convert struct _ddebug to use struct codetag; another
cleanup could convert it to that, and to codetag_query_parse().

Signed-off-by: Kent Overstreet <kent.overstreet@xxxxxxxxx>
Cc: Jason Baron <jbaron@xxxxxxxxxx>
Cc: Luis Chamberlain <mcgrof@xxxxxxxxxx>
---
 include/asm-generic/codetag.lds.h |   5 +-
 include/asm-generic/vmlinux.lds.h |   5 -
 include/linux/dynamic_debug.h     |  11 +-
 kernel/module/internal.h          |   2 -
 kernel/module/main.c              |  23 --
 lib/dynamic_debug.c               | 452 ++++++++++--------------------
 6 files changed, 158 insertions(+), 340 deletions(-)

diff --git a/include/asm-generic/codetag.lds.h 
b/include/asm-generic/codetag.lds.h
index b087cf1874a9..b7e351f80e9e 100644
--- a/include/asm-generic/codetag.lds.h
+++ b/include/asm-generic/codetag.lds.h
@@ -8,10 +8,11 @@
        KEEP(*(_name))                  \
        __stop_##_name = .;
 
-#define CODETAG_SECTIONS()             \
+#define CODETAG_SECTIONS()                             \
        SECTION_WITH_BOUNDARIES(alloc_tags)             \
        SECTION_WITH_BOUNDARIES(dynamic_fault_tags)     \
        SECTION_WITH_BOUNDARIES(time_stats_tags)        \
-       SECTION_WITH_BOUNDARIES(error_code_tags)
+       SECTION_WITH_BOUNDARIES(error_code_tags)        \
+       SECTION_WITH_BOUNDARIES(dyndbg)
 
 #endif /* __ASM_GENERIC_CODETAG_LDS_H */
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index c2dc2a59ab2e..d3fb914d157f 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -345,11 +345,6 @@
        __end_once = .;                                                 \
        STRUCT_ALIGN();                                                 \
        *(__tracepoints)                                                \
-       /* implement dynamic printk debug */                            \
-       . = ALIGN(8);                                                   \
-       __start___dyndbg = .;                                           \
-       KEEP(*(__dyndbg))                                               \
-       __stop___dyndbg = .;                                            \
        CODETAG_SECTIONS()                                              \
        LIKELY_PROFILE()                                                \
        BRANCH_PROFILE()                                                \
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index dce631e678dd..6a57009dd29e 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -58,9 +58,6 @@ struct _ddebug {
 /* exported for module authors to exercise >control */
 int dynamic_debug_exec_queries(const char *query, const char *modname);
 
-int ddebug_add_module(struct _ddebug *tab, unsigned int n,
-                               const char *modname);
-extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
 
@@ -89,7 +86,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)               \
        static struct _ddebug  __aligned(8)                     \
-       __section("__dyndbg") name = {                          \
+       __section("dyndbg") name = {                            \
                .modname = KBUILD_MODNAME,                      \
                .function = __func__,                           \
                .filename = __FILE__,                           \
@@ -187,12 +184,6 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 #include <linux/errno.h>
 #include <linux/printk.h>
 
-static inline int ddebug_add_module(struct _ddebug *tab, unsigned int n,
-                                   const char *modname)
-{
-       return 0;
-}
-
 static inline int ddebug_remove_module(const char *mod)
 {
        return 0;
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index f1b6c477bd93..f867c57ab74f 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -62,8 +62,6 @@ struct load_info {
        Elf_Shdr *sechdrs;
        char *secstrings, *strtab;
        unsigned long symoffs, stroffs, init_typeoffs, core_typeoffs;
-       struct _ddebug *debug;
-       unsigned int num_debug;
        bool sig_ok;
 #ifdef CONFIG_KALLSYMS
        unsigned long mod_kallsyms_init_off;
diff --git a/kernel/module/main.c b/kernel/module/main.c
index d253277492fd..28e3b337841b 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1163,9 +1163,6 @@ static void free_module(struct module *mod)
        mod->state = MODULE_STATE_UNFORMED;
        mutex_unlock(&module_mutex);
 
-       /* Remove dynamic debug info */
-       ddebug_remove_module(mod->name);
-
        /* Arch-specific cleanup. */
        module_arch_cleanup(mod);
 
@@ -1600,19 +1597,6 @@ static void free_modinfo(struct module *mod)
        }
 }
 
-static void dynamic_debug_setup(struct module *mod, struct _ddebug *debug, 
unsigned int num)
-{
-       if (!debug)
-               return;
-       ddebug_add_module(debug, num, mod->name);
-}
-
-static void dynamic_debug_remove(struct module *mod, struct _ddebug *debug)
-{
-       if (debug)
-               ddebug_remove_module(mod->name);
-}
-
 void * __weak module_alloc(unsigned long size)
 {
        return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
@@ -2113,9 +2097,6 @@ static int find_module_sections(struct module *mod, 
struct load_info *info)
        if (section_addr(info, "__obsparm"))
                pr_warn("%s: Ignoring obsolete parameters\n", mod->name);
 
-       info->debug = section_objs(info, "__dyndbg",
-                                  sizeof(*info->debug), &info->num_debug);
-
        return 0;
 }
 
@@ -2808,9 +2789,6 @@ static int load_module(struct load_info *info, const char 
__user *uargs,
                goto free_arch_cleanup;
        }
 
-       init_build_id(mod, info);
-       dynamic_debug_setup(mod, info->debug, info->num_debug);
-
        /* Ftrace init must be called in the MODULE_STATE_UNFORMED state */
        ftrace_module_init(mod);
 
@@ -2875,7 +2853,6 @@ static int load_module(struct load_info *info, const char 
__user *uargs,
 
  ddebug_cleanup:
        ftrace_release_mod(mod);
-       dynamic_debug_remove(mod, info->debug);
        synchronize_rcu();
        kfree(mod->args);
  free_arch_cleanup:
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index dd7f56af9aed..e9079825fb3b 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -13,6 +13,7 @@
 
 #define pr_fmt(fmt) "dyndbg: " fmt
 
+#include <linux/codetag.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -36,19 +37,37 @@
 #include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/netdevice.h>
+#include <linux/seq_buf.h>
 
 #include <rdma/ib_verbs.h>
 
-extern struct _ddebug __start___dyndbg[];
-extern struct _ddebug __stop___dyndbg[];
+static struct codetag_type *cttype;
 
-struct ddebug_table {
-       struct list_head link;
-       const char *mod_name;
-       unsigned int num_ddebugs;
-       struct _ddebug *ddebugs;
+struct user_buf {
+       char __user             *buf;   /* destination user buffer */
+       size_t                  size;   /* size of requested read */
+       ssize_t                 ret;    /* bytes read so far */
 };
 
+static int flush_ubuf(struct user_buf *dst, struct seq_buf *src)
+{
+       if (src->len) {
+               size_t bytes = min_t(size_t, src->len, dst->size);
+               int err = copy_to_user(dst->buf, src->buffer, bytes);
+
+               if (err)
+                       return err;
+
+               dst->ret        += bytes;
+               dst->buf        += bytes;
+               dst->size       -= bytes;
+               src->len        -= bytes;
+               memmove(src->buffer, src->buffer + bytes, src->len);
+       }
+
+       return 0;
+}
+
 struct ddebug_query {
        const char *filename;
        const char *module;
@@ -58,8 +77,9 @@ struct ddebug_query {
 };
 
 struct ddebug_iter {
-       struct ddebug_table *table;
-       unsigned int idx;
+       struct codetag_iterator ct_iter;
+       struct seq_buf          buf;
+       char                    rawbuf[4096];
 };
 
 struct flag_settings {
@@ -67,8 +87,6 @@ struct flag_settings {
        unsigned int mask;
 };
 
-static DEFINE_MUTEX(ddebug_lock);
-static LIST_HEAD(ddebug_tables);
 static int verbose;
 module_param(verbose, int, 0644);
 MODULE_PARM_DESC(verbose, " dynamic_debug/control processing "
@@ -152,78 +170,76 @@ static void vpr_info_dq(const struct ddebug_query *query, 
const char *msg)
 static int ddebug_change(const struct ddebug_query *query,
                         struct flag_settings *modifiers)
 {
-       int i;
-       struct ddebug_table *dt;
+       struct codetag_iterator ct_iter;
+       struct codetag *ct;
        unsigned int newflags;
        unsigned int nfound = 0;
        struct flagsbuf fbuf;
 
-       /* search for matching ddebugs */
-       mutex_lock(&ddebug_lock);
-       list_for_each_entry(dt, &ddebug_tables, link) {
+       codetag_lock_module_list(cttype, true);
+       codetag_init_iter(&ct_iter, cttype);
+
+       while ((ct = codetag_next_ct(&ct_iter))) {
+               struct _ddebug *dp = (void *) ct;
 
                /* match against the module name */
                if (query->module &&
-                   !match_wildcard(query->module, dt->mod_name))
+                   !match_wildcard(query->module, dp->modname))
                        continue;
 
-               for (i = 0; i < dt->num_ddebugs; i++) {
-                       struct _ddebug *dp = &dt->ddebugs[i];
-
-                       /* match against the source filename */
-                       if (query->filename &&
-                           !match_wildcard(query->filename, dp->filename) &&
-                           !match_wildcard(query->filename,
-                                          kbasename(dp->filename)) &&
-                           !match_wildcard(query->filename,
-                                          trim_prefix(dp->filename)))
-                               continue;
+               /* match against the source filename */
+               if (query->filename &&
+                   !match_wildcard(query->filename, dp->filename) &&
+                   !match_wildcard(query->filename,
+                                  kbasename(dp->filename)) &&
+                   !match_wildcard(query->filename,
+                                  trim_prefix(dp->filename)))
+                       continue;
 
-                       /* match against the function */
-                       if (query->function &&
-                           !match_wildcard(query->function, dp->function))
-                               continue;
+               /* match against the function */
+               if (query->function &&
+                   !match_wildcard(query->function, dp->function))
+                       continue;
 
-                       /* match against the format */
-                       if (query->format) {
-                               if (*query->format == '^') {
-                                       char *p;
-                                       /* anchored search. match must be at 
beginning */
-                                       p = strstr(dp->format, query->format+1);
-                                       if (p != dp->format)
-                                               continue;
-                               } else if (!strstr(dp->format, query->format))
+               /* match against the format */
+               if (query->format) {
+                       if (*query->format == '^') {
+                               char *p;
+                               /* anchored search. match must be at beginning 
*/
+                               p = strstr(dp->format, query->format+1);
+                               if (p != dp->format)
                                        continue;
-                       }
-
-                       /* match against the line number range */
-                       if (query->first_lineno &&
-                           dp->lineno < query->first_lineno)
-                               continue;
-                       if (query->last_lineno &&
-                           dp->lineno > query->last_lineno)
+                       } else if (!strstr(dp->format, query->format))
                                continue;
+               }
+
+               /* match against the line number range */
+               if (query->first_lineno &&
+                   dp->lineno < query->first_lineno)
+                       continue;
+               if (query->last_lineno &&
+                   dp->lineno > query->last_lineno)
+                       continue;
 
-                       nfound++;
+               nfound++;
 
-                       newflags = (dp->flags & modifiers->mask) | 
modifiers->flags;
-                       if (newflags == dp->flags)
-                               continue;
+               newflags = (dp->flags & modifiers->mask) | modifiers->flags;
+               if (newflags == dp->flags)
+                       continue;
 #ifdef CONFIG_JUMP_LABEL
-                       if (dp->flags & _DPRINTK_FLAGS_PRINT) {
-                               if (!(modifiers->flags & _DPRINTK_FLAGS_PRINT))
-                                       
static_branch_disable(&dp->key.dd_key_true);
-                       } else if (modifiers->flags & _DPRINTK_FLAGS_PRINT)
-                               static_branch_enable(&dp->key.dd_key_true);
+               if (dp->flags & _DPRINTK_FLAGS_PRINT) {
+                       if (!(modifiers->flags & _DPRINTK_FLAGS_PRINT))
+                               static_branch_disable(&dp->key.dd_key_true);
+               } else if (modifiers->flags & _DPRINTK_FLAGS_PRINT)
+                       static_branch_enable(&dp->key.dd_key_true);
 #endif
-                       dp->flags = newflags;
-                       v4pr_info("changed %s:%d [%s]%s =%s\n",
-                                trim_prefix(dp->filename), dp->lineno,
-                                dt->mod_name, dp->function,
-                                ddebug_describe_flags(dp->flags, &fbuf));
-               }
+               dp->flags = newflags;
+               v4pr_info("changed %s:%d [%s]%s =%s\n",
+                        trim_prefix(dp->filename), dp->lineno,
+                        dp->modname, dp->function,
+                        ddebug_describe_flags(dp->flags, &fbuf));
        }
-       mutex_unlock(&ddebug_lock);
+       codetag_lock_module_list(cttype, false);
 
        if (!nfound && verbose)
                pr_info("no matches for query\n");
@@ -794,187 +810,96 @@ static ssize_t ddebug_proc_write(struct file *file, 
const char __user *ubuf,
        return len;
 }
 
-/*
- * Set the iterator to point to the first _ddebug object
- * and return a pointer to that first object.  Returns
- * NULL if there are no _ddebugs at all.
- */
-static struct _ddebug *ddebug_iter_first(struct ddebug_iter *iter)
-{
-       if (list_empty(&ddebug_tables)) {
-               iter->table = NULL;
-               iter->idx = 0;
-               return NULL;
-       }
-       iter->table = list_entry(ddebug_tables.next,
-                                struct ddebug_table, link);
-       iter->idx = 0;
-       return &iter->table->ddebugs[iter->idx];
-}
-
-/*
- * Advance the iterator to point to the next _ddebug
- * object from the one the iterator currently points at,
- * and returns a pointer to the new _ddebug.  Returns
- * NULL if the iterator has seen all the _ddebugs.
- */
-static struct _ddebug *ddebug_iter_next(struct ddebug_iter *iter)
-{
-       if (iter->table == NULL)
-               return NULL;
-       if (++iter->idx == iter->table->num_ddebugs) {
-               /* iterate to next table */
-               iter->idx = 0;
-               if (list_is_last(&iter->table->link, &ddebug_tables)) {
-                       iter->table = NULL;
-                       return NULL;
-               }
-               iter->table = list_entry(iter->table->link.next,
-                                        struct ddebug_table, link);
-       }
-       return &iter->table->ddebugs[iter->idx];
-}
-
-/*
- * Seq_ops start method.  Called at the start of every
- * read() call from userspace.  Takes the ddebug_lock and
- * seeks the seq_file's iterator to the given position.
- */
-static void *ddebug_proc_start(struct seq_file *m, loff_t *pos)
-{
-       struct ddebug_iter *iter = m->private;
-       struct _ddebug *dp;
-       int n = *pos;
-
-       mutex_lock(&ddebug_lock);
-
-       if (!n)
-               return SEQ_START_TOKEN;
-       if (n < 0)
-               return NULL;
-       dp = ddebug_iter_first(iter);
-       while (dp != NULL && --n > 0)
-               dp = ddebug_iter_next(iter);
-       return dp;
-}
-
-/*
- * Seq_ops next method.  Called several times within a read()
- * call from userspace, with ddebug_lock held.  Walks to the
- * next _ddebug object with a special case for the header line.
- */
-static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
-{
-       struct ddebug_iter *iter = m->private;
-       struct _ddebug *dp;
-
-       if (p == SEQ_START_TOKEN)
-               dp = ddebug_iter_first(iter);
-       else
-               dp = ddebug_iter_next(iter);
-       ++*pos;
-       return dp;
-}
-
 /*
  * Seq_ops show method.  Called several times within a read()
  * call from userspace, with ddebug_lock held.  Formats the
  * current _ddebug as a single human-readable line, with a
  * special case for the header line.
  */
-static int ddebug_proc_show(struct seq_file *m, void *p)
+static void ddebug_to_text(struct seq_buf *out, struct _ddebug *dp)
 {
-       struct ddebug_iter *iter = m->private;
-       struct _ddebug *dp = p;
        struct flagsbuf flags;
+       char *buf;
+       size_t len;
 
-       if (p == SEQ_START_TOKEN) {
-               seq_puts(m,
-                        "# filename:lineno [module]function flags format\n");
-               return 0;
-       }
-
-       seq_printf(m, "%s:%u [%s]%s =%s \"",
+       seq_buf_printf(out, "%s:%u [%s]%s =%s \"",
                   trim_prefix(dp->filename), dp->lineno,
-                  iter->table->mod_name, dp->function,
+                  dp->modname, dp->function,
                   ddebug_describe_flags(dp->flags, &flags));
-       seq_escape(m, dp->format, "\t\r\n\"");
-       seq_puts(m, "\"\n");
 
-       return 0;
-}
+       len = seq_buf_get_buf(out, &buf);
+       len = string_escape_mem(dp->format, strlen(dp->format),
+                               buf, len, ESCAPE_OCTAL, "\t\r\n\"");
+       seq_buf_commit(out, len);
 
-/*
- * Seq_ops stop method.  Called at the end of each read()
- * call from userspace.  Drops ddebug_lock.
- */
-static void ddebug_proc_stop(struct seq_file *m, void *p)
-{
-       mutex_unlock(&ddebug_lock);
+       seq_buf_puts(out, "\"\n");
 }
 
-static const struct seq_operations ddebug_proc_seqops = {
-       .start = ddebug_proc_start,
-       .next = ddebug_proc_next,
-       .show = ddebug_proc_show,
-       .stop = ddebug_proc_stop
-};
-
 static int ddebug_proc_open(struct inode *inode, struct file *file)
 {
-       return seq_open_private(file, &ddebug_proc_seqops,
-                               sizeof(struct ddebug_iter));
+       struct ddebug_iter *iter;
+
+       iter = kzalloc(sizeof(*iter), GFP_KERNEL);
+       if (!iter)
+               return -ENOMEM;
+
+       codetag_lock_module_list(cttype, true);
+       codetag_init_iter(&iter->ct_iter, cttype);
+       codetag_lock_module_list(cttype, false);
+       seq_buf_init(&iter->buf, iter->rawbuf, sizeof(iter->rawbuf));
+       file->private_data = iter;
+
+       return 0;
 }
 
-static const struct file_operations ddebug_proc_fops = {
-       .owner = THIS_MODULE,
-       .open = ddebug_proc_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release_private,
-       .write = ddebug_proc_write
-};
+static int ddebug_proc_release(struct inode *inode, struct file *file)
+{
+       struct ddebug_iter *iter = file->private_data;
 
-static const struct proc_ops proc_fops = {
-       .proc_open = ddebug_proc_open,
-       .proc_read = seq_read,
-       .proc_lseek = seq_lseek,
-       .proc_release = seq_release_private,
-       .proc_write = ddebug_proc_write
-};
+       kfree(iter);
+       return 0;
+}
 
-/*
- * Allocate a new ddebug_table for the given module
- * and add it to the global list.
- */
-int ddebug_add_module(struct _ddebug *tab, unsigned int n,
-                            const char *name)
+static ssize_t ddebug_proc_read(struct file *file, char __user *ubuf,
+                                  size_t size, loff_t *ppos)
 {
-       struct ddebug_table *dt;
+       struct ddebug_iter *iter = file->private_data;
+       struct user_buf buf = { .buf = ubuf, .size = size };
+       struct codetag *ct;
+       int err = 0;
 
-       dt = kzalloc(sizeof(*dt), GFP_KERNEL);
-       if (dt == NULL) {
-               pr_err("error adding module: %s\n", name);
-               return -ENOMEM;
-       }
-       /*
-        * For built-in modules, name lives in .rodata and is
-        * immortal. For loaded modules, name points at the name[]
-        * member of struct module, which lives at least as long as
-        * this struct ddebug_table.
-        */
-       dt->mod_name = name;
-       dt->num_ddebugs = n;
-       dt->ddebugs = tab;
+       codetag_lock_module_list(iter->ct_iter.cttype, true);
+       while (1) {
+               err = flush_ubuf(&buf, &iter->buf);
+               if (err || !buf.size)
+                       break;
+
+               ct = codetag_next_ct(&iter->ct_iter);
+               if (!ct)
+                       break;
 
-       mutex_lock(&ddebug_lock);
-       list_add(&dt->link, &ddebug_tables);
-       mutex_unlock(&ddebug_lock);
+               ddebug_to_text(&iter->buf, (void *) ct);
+       }
+       codetag_lock_module_list(iter->ct_iter.cttype, false);
 
-       vpr_info("%3u debug prints in module %s\n", n, dt->mod_name);
-       return 0;
+       return err ? : buf.ret;
 }
 
+static const struct file_operations ddebug_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = ddebug_proc_open,
+       .read           = ddebug_proc_read,
+       .release        = ddebug_proc_release,
+       .write          = ddebug_proc_write,
+};
+
+static const struct proc_ops proc_fops = {
+       .proc_open      = ddebug_proc_open,
+       .proc_read      = ddebug_proc_read,
+       .proc_release   = ddebug_proc_release,
+       .proc_write     = ddebug_proc_write,
+};
+
 /* helper for ddebug_dyndbg_(boot|module)_param_cb */
 static int ddebug_dyndbg_param_cb(char *param, char *val,
                                const char *modname, int on_err)
@@ -1015,47 +940,6 @@ int ddebug_dyndbg_module_param_cb(char *param, char *val, 
const char *module)
        return ddebug_dyndbg_param_cb(param, val, module, -ENOENT);
 }
 
-static void ddebug_table_free(struct ddebug_table *dt)
-{
-       list_del_init(&dt->link);
-       kfree(dt);
-}
-
-/*
- * Called in response to a module being unloaded.  Removes
- * any ddebug_table's which point at the module.
- */
-int ddebug_remove_module(const char *mod_name)
-{
-       struct ddebug_table *dt, *nextdt;
-       int ret = -ENOENT;
-
-       mutex_lock(&ddebug_lock);
-       list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) {
-               if (dt->mod_name == mod_name) {
-                       ddebug_table_free(dt);
-                       ret = 0;
-                       break;
-               }
-       }
-       mutex_unlock(&ddebug_lock);
-       if (!ret)
-               v2pr_info("removed module \"%s\"\n", mod_name);
-       return ret;
-}
-
-static void ddebug_remove_all_tables(void)
-{
-       mutex_lock(&ddebug_lock);
-       while (!list_empty(&ddebug_tables)) {
-               struct ddebug_table *dt = list_entry(ddebug_tables.next,
-                                                     struct ddebug_table,
-                                                     link);
-               ddebug_table_free(dt);
-       }
-       mutex_unlock(&ddebug_lock);
-}
-
 static __initdata int ddebug_init_success;
 
 static int __init dynamic_debug_init_control(void)
@@ -1083,45 +967,19 @@ static int __init dynamic_debug_init_control(void)
 
 static int __init dynamic_debug_init(void)
 {
-       struct _ddebug *iter, *iter_start;
-       const char *modname = NULL;
+       const struct codetag_type_desc desc = {
+               .section = "dyndbg",
+               .tag_size = sizeof(struct _ddebug),
+       };
        char *cmdline;
-       int ret = 0;
-       int n = 0, entries = 0, modct = 0;
+       int ret;
 
-       if (&__start___dyndbg == &__stop___dyndbg) {
-               if (IS_ENABLED(CONFIG_DYNAMIC_DEBUG)) {
-                       pr_warn("_ddebug table is empty in a 
CONFIG_DYNAMIC_DEBUG build\n");
-                       return 1;
-               }
-               pr_info("Ignore empty _ddebug table in a 
CONFIG_DYNAMIC_DEBUG_CORE build\n");
-               ddebug_init_success = 1;
-               return 0;
-       }
-       iter = __start___dyndbg;
-       modname = iter->modname;
-       iter_start = iter;
-       for (; iter < __stop___dyndbg; iter++) {
-               entries++;
-               if (strcmp(modname, iter->modname)) {
-                       modct++;
-                       ret = ddebug_add_module(iter_start, n, modname);
-                       if (ret)
-                               goto out_err;
-                       n = 0;
-                       modname = iter->modname;
-                       iter_start = iter;
-               }
-               n++;
-       }
-       ret = ddebug_add_module(iter_start, n, modname);
+       cttype = codetag_register_type(&desc);
+       ret = PTR_ERR_OR_ZERO(cttype);
        if (ret)
-               goto out_err;
+               return ret;
 
        ddebug_init_success = 1;
-       vpr_info("%d prdebugs in %d modules, %d KiB in ddebug tables, %d kiB in 
__dyndbg section\n",
-                entries, modct, (int)((modct * sizeof(struct ddebug_table)) >> 
10),
-                (int)((entries * sizeof(struct _ddebug)) >> 10));
 
        /* now that ddebug tables are loaded, process all boot args
         * again to find and activate queries given in dyndbg params.
@@ -1132,14 +990,12 @@ static int __init dynamic_debug_init(void)
         * slightly noisy if verbose, but harmless.
         */
        cmdline = kstrdup(saved_command_line, GFP_KERNEL);
+       if (!cmdline)
+               return -ENOMEM;
        parse_args("dyndbg params", cmdline, NULL,
                   0, 0, 0, NULL, &ddebug_dyndbg_boot_param_cb);
        kfree(cmdline);
        return 0;
-
-out_err:
-       ddebug_remove_all_tables();
-       return 0;
 }
 /* Allow early initialization for boot messages via boot param */
 early_initcall(dynamic_debug_init);
-- 
2.37.2.672.g94769d06f0-goog




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.