Commit 7ead8b8313d92b3a69a1a61b0dcbc4cd66c960dc

Authored by Li Zefan
Committed by Ingo Molnar
1 parent 60d970c254

tracing/events: Add module tracepoints

Add trace points to trace module_load, module_free, module_get,
module_put and module_request, and use trace_event facility to
get the trace output.

Here's the sample output:

     TASK-PID    CPU#    TIMESTAMP  FUNCTION
        | |       |          |         |
    <...>-42    [000]     1.758380: module_request: fb0 wait=1 call_site=fb_open
    ...
    <...>-60    [000]     3.269403: module_load: scsi_wait_scan
    <...>-60    [000]     3.269432: module_put: scsi_wait_scan call_site=sys_init_module refcnt=0
    <...>-61    [001]     3.273168: module_free: scsi_wait_scan
    ...
    <...>-1021  [000]    13.836081: module_load: sunrpc
    <...>-1021  [000]    13.840589: module_put: sunrpc call_site=sys_init_module refcnt=-1
    <...>-1027  [000]    13.848098: module_get: sunrpc call_site=try_module_get refcnt=0
    <...>-1027  [000]    13.848308: module_get: sunrpc call_site=get_filesystem refcnt=1
    <...>-1027  [000]    13.848692: module_put: sunrpc call_site=put_filesystem refcnt=0
    ...
 modprobe-2587  [001]  1088.437213: module_load: trace_events_sample F
 modprobe-2587  [001]  1088.437786: module_put: trace_events_sample call_site=sys_init_module refcnt=0

Note:

- the taints flag can be 'F', 'C' and/or 'P' if mod->taints != 0

- the module refcnt is percpu, so it can be negative in a
  specific cpu

Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Acked-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
LKML-Reference: <4A891B3C.5030608@cn.fujitsu.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

Showing 4 changed files with 152 additions and 3 deletions Side-by-side Diff

include/linux/module.h
... ... @@ -17,10 +17,12 @@
17 17 #include <linux/moduleparam.h>
18 18 #include <linux/marker.h>
19 19 #include <linux/tracepoint.h>
20   -#include <asm/local.h>
21 20  
  21 +#include <asm/local.h>
22 22 #include <asm/module.h>
23 23  
  24 +#include <trace/events/module.h>
  25 +
24 26 /* Not Yet Implemented */
25 27 #define MODULE_SUPPORTED_DEVICE(name)
26 28  
... ... @@ -462,7 +464,10 @@
462 464 static inline void __module_get(struct module *module)
463 465 {
464 466 if (module) {
465   - local_inc(__module_ref_addr(module, get_cpu()));
  467 + unsigned int cpu = get_cpu();
  468 + local_inc(__module_ref_addr(module, cpu));
  469 + trace_module_get(module, _THIS_IP_,
  470 + local_read(__module_ref_addr(module, cpu)));
466 471 put_cpu();
467 472 }
468 473 }
469 474  
... ... @@ -473,8 +478,11 @@
473 478  
474 479 if (module) {
475 480 unsigned int cpu = get_cpu();
476   - if (likely(module_is_live(module)))
  481 + if (likely(module_is_live(module))) {
477 482 local_inc(__module_ref_addr(module, cpu));
  483 + trace_module_get(module, _THIS_IP_,
  484 + local_read(__module_ref_addr(module, cpu)));
  485 + }
478 486 else
479 487 ret = 0;
480 488 put_cpu();
include/trace/events/module.h
  1 +#undef TRACE_SYSTEM
  2 +#define TRACE_SYSTEM module
  3 +
  4 +#if !defined(_TRACE_MODULE_H) || defined(TRACE_HEADER_MULTI_READ)
  5 +#define _TRACE_MODULE_H
  6 +
  7 +#include <linux/tracepoint.h>
  8 +
  9 +#ifdef CONFIG_MODULES
  10 +
  11 +struct module;
  12 +
  13 +#define show_module_flags(flags) __print_flags(flags, "", \
  14 + { (1UL << TAINT_PROPRIETARY_MODULE), "P" }, \
  15 + { (1UL << TAINT_FORCED_MODULE), "F" }, \
  16 + { (1UL << TAINT_CRAP), "C" })
  17 +
  18 +TRACE_EVENT(module_load,
  19 +
  20 + TP_PROTO(struct module *mod),
  21 +
  22 + TP_ARGS(mod),
  23 +
  24 + TP_STRUCT__entry(
  25 + __field( unsigned int, taints )
  26 + __string( name, mod->name )
  27 + ),
  28 +
  29 + TP_fast_assign(
  30 + __entry->taints = mod->taints;
  31 + __assign_str(name, mod->name);
  32 + ),
  33 +
  34 + TP_printk("%s %s", __get_str(name), show_module_flags(__entry->taints))
  35 +);
  36 +
  37 +TRACE_EVENT(module_free,
  38 +
  39 + TP_PROTO(struct module *mod),
  40 +
  41 + TP_ARGS(mod),
  42 +
  43 + TP_STRUCT__entry(
  44 + __string( name, mod->name )
  45 + ),
  46 +
  47 + TP_fast_assign(
  48 + __assign_str(name, mod->name);
  49 + ),
  50 +
  51 + TP_printk("%s", __get_str(name))
  52 +);
  53 +
  54 +TRACE_EVENT(module_get,
  55 +
  56 + TP_PROTO(struct module *mod, unsigned long ip, int refcnt),
  57 +
  58 + TP_ARGS(mod, ip, refcnt),
  59 +
  60 + TP_STRUCT__entry(
  61 + __field( unsigned long, ip )
  62 + __field( int, refcnt )
  63 + __string( name, mod->name )
  64 + ),
  65 +
  66 + TP_fast_assign(
  67 + __entry->ip = ip;
  68 + __entry->refcnt = refcnt;
  69 + __assign_str(name, mod->name);
  70 + ),
  71 +
  72 + TP_printk("%s call_site=%pf refcnt=%d",
  73 + __get_str(name), (void *)__entry->ip, __entry->refcnt)
  74 +);
  75 +
  76 +TRACE_EVENT(module_put,
  77 +
  78 + TP_PROTO(struct module *mod, unsigned long ip, int refcnt),
  79 +
  80 + TP_ARGS(mod, ip, refcnt),
  81 +
  82 + TP_STRUCT__entry(
  83 + __field( unsigned long, ip )
  84 + __field( int, refcnt )
  85 + __string( name, mod->name )
  86 + ),
  87 +
  88 + TP_fast_assign(
  89 + __entry->ip = ip;
  90 + __entry->refcnt = refcnt;
  91 + __assign_str(name, mod->name);
  92 + ),
  93 +
  94 + TP_printk("%s call_site=%pf refcnt=%d",
  95 + __get_str(name), (void *)__entry->ip, __entry->refcnt)
  96 +);
  97 +
  98 +TRACE_EVENT(module_request,
  99 +
  100 + TP_PROTO(char *name, bool wait, unsigned long ip),
  101 +
  102 + TP_ARGS(name, wait, ip),
  103 +
  104 + TP_STRUCT__entry(
  105 + __field( bool, wait )
  106 + __field( unsigned long, ip )
  107 + __string( name, name )
  108 + ),
  109 +
  110 + TP_fast_assign(
  111 + __entry->wait = wait;
  112 + __entry->ip = ip;
  113 + __assign_str(name, name);
  114 + ),
  115 +
  116 + TP_printk("%s wait=%d call_site=%pf",
  117 + __get_str(name), (int)__entry->wait, (void *)__entry->ip)
  118 +);
  119 +
  120 +#endif /* CONFIG_MODULES */
  121 +
  122 +#endif /* _TRACE_MODULE_H */
  123 +
  124 +/* This part must be outside protection */
  125 +#include <trace/define_trace.h>
... ... @@ -37,6 +37,8 @@
37 37 #include <linux/suspend.h>
38 38 #include <asm/uaccess.h>
39 39  
  40 +#include <trace/events/module.h>
  41 +
40 42 extern int max_threads;
41 43  
42 44 static struct workqueue_struct *khelper_wq;
... ... @@ -107,6 +109,8 @@
107 109 atomic_dec(&kmod_concurrent);
108 110 return -ENOMEM;
109 111 }
  112 +
  113 + trace_module_request(module_name, wait, _RET_IP_);
110 114  
111 115 ret = call_usermodehelper(modprobe_path, argv, envp,
112 116 wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC);
... ... @@ -55,6 +55,11 @@
55 55 #include <linux/percpu.h>
56 56 #include <linux/kmemleak.h>
57 57  
  58 +#define CREATE_TRACE_POINTS
  59 +#include <trace/events/module.h>
  60 +
  61 +EXPORT_TRACEPOINT_SYMBOL(module_get);
  62 +
58 63 #if 0
59 64 #define DEBUGP printk
60 65 #else
... ... @@ -940,6 +945,8 @@
940 945 if (module) {
941 946 unsigned int cpu = get_cpu();
942 947 local_dec(__module_ref_addr(module, cpu));
  948 + trace_module_put(module, _RET_IP_,
  949 + local_read(__module_ref_addr(module, cpu)));
943 950 /* Maybe they're waiting for us to drop reference? */
944 951 if (unlikely(!module_is_live(module)))
945 952 wake_up_process(module->waiter);
... ... @@ -1491,6 +1498,8 @@
1491 1498 /* Free a module, remove from lists, etc (must hold module_mutex). */
1492 1499 static void free_module(struct module *mod)
1493 1500 {
  1501 + trace_module_free(mod);
  1502 +
1494 1503 /* Delete from various lists */
1495 1504 stop_machine(__unlink_module, mod, NULL);
1496 1505 remove_notes_attrs(mod);
... ... @@ -2357,6 +2366,8 @@
2357 2366  
2358 2367 /* Get rid of temporary copy */
2359 2368 vfree(hdr);
  2369 +
  2370 + trace_module_load(mod);
2360 2371  
2361 2372 /* Done! */
2362 2373 return mod;