trace_printk.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * trace binary printk
  3. *
  4. * Copyright (C) 2008 Lai Jiangshan <laijs@cn.fujitsu.com>
  5. *
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/ftrace.h>
  9. #include <linux/string.h>
  10. #include <linux/ctype.h>
  11. #include <linux/list.h>
  12. #include <linux/mutex.h>
  13. #include <linux/slab.h>
  14. #include <linux/module.h>
  15. #include <linux/seq_file.h>
  16. #include <linux/fs.h>
  17. #include <linux/marker.h>
  18. #include <linux/uaccess.h>
  19. #include "trace.h"
  20. #ifdef CONFIG_MODULES
  21. /*
  22. * modules trace_printk()'s formats are autosaved in struct trace_bprintk_fmt
  23. * which are queued on trace_bprintk_fmt_list.
  24. */
  25. static LIST_HEAD(trace_bprintk_fmt_list);
  26. /* serialize accesses to trace_bprintk_fmt_list */
  27. static DEFINE_MUTEX(btrace_mutex);
  28. struct trace_bprintk_fmt {
  29. struct list_head list;
  30. char fmt[0];
  31. };
  32. static inline struct trace_bprintk_fmt *lookup_format(const char *fmt)
  33. {
  34. struct trace_bprintk_fmt *pos;
  35. list_for_each_entry(pos, &trace_bprintk_fmt_list, list) {
  36. if (!strcmp(pos->fmt, fmt))
  37. return pos;
  38. }
  39. return NULL;
  40. }
  41. static
  42. void hold_module_trace_bprintk_format(const char **start, const char **end)
  43. {
  44. const char **iter;
  45. mutex_lock(&btrace_mutex);
  46. for (iter = start; iter < end; iter++) {
  47. struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter);
  48. if (tb_fmt) {
  49. *iter = tb_fmt->fmt;
  50. continue;
  51. }
  52. tb_fmt = kmalloc(offsetof(struct trace_bprintk_fmt, fmt)
  53. + strlen(*iter) + 1, GFP_KERNEL);
  54. if (tb_fmt) {
  55. list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list);
  56. strcpy(tb_fmt->fmt, *iter);
  57. *iter = tb_fmt->fmt;
  58. } else
  59. *iter = NULL;
  60. }
  61. mutex_unlock(&btrace_mutex);
  62. }
  63. static int module_trace_bprintk_format_notify(struct notifier_block *self,
  64. unsigned long val, void *data)
  65. {
  66. struct module *mod = data;
  67. if (mod->num_trace_bprintk_fmt) {
  68. const char **start = mod->trace_bprintk_fmt_start;
  69. const char **end = start + mod->num_trace_bprintk_fmt;
  70. if (val == MODULE_STATE_COMING)
  71. hold_module_trace_bprintk_format(start, end);
  72. }
  73. return 0;
  74. }
  75. #else /* !CONFIG_MODULES */
  76. __init static int
  77. module_trace_bprintk_format_notify(struct notifier_block *self,
  78. unsigned long val, void *data)
  79. {
  80. return 0;
  81. }
  82. #endif /* CONFIG_MODULES */
  83. __initdata_or_module static
  84. struct notifier_block module_trace_bprintk_format_nb = {
  85. .notifier_call = module_trace_bprintk_format_notify,
  86. };
  87. int __trace_bprintk(unsigned long ip, const char *fmt, ...)
  88. {
  89. int ret;
  90. va_list ap;
  91. if (unlikely(!fmt))
  92. return 0;
  93. if (!(trace_flags & TRACE_ITER_PRINTK))
  94. return 0;
  95. va_start(ap, fmt);
  96. ret = trace_vbprintk(ip, task_curr_ret_stack(current), fmt, ap);
  97. va_end(ap);
  98. return ret;
  99. }
  100. EXPORT_SYMBOL_GPL(__trace_bprintk);
  101. int __ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap)
  102. {
  103. if (unlikely(!fmt))
  104. return 0;
  105. if (!(trace_flags & TRACE_ITER_PRINTK))
  106. return 0;
  107. return trace_vbprintk(ip, task_curr_ret_stack(current), fmt, ap);
  108. }
  109. EXPORT_SYMBOL_GPL(__ftrace_vbprintk);
  110. int __trace_printk(unsigned long ip, const char *fmt, ...)
  111. {
  112. int ret;
  113. va_list ap;
  114. if (!(trace_flags & TRACE_ITER_PRINTK))
  115. return 0;
  116. va_start(ap, fmt);
  117. ret = trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap);
  118. va_end(ap);
  119. return ret;
  120. }
  121. EXPORT_SYMBOL_GPL(__trace_printk);
  122. int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap)
  123. {
  124. if (!(trace_flags & TRACE_ITER_PRINTK))
  125. return 0;
  126. return trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap);
  127. }
  128. EXPORT_SYMBOL_GPL(__ftrace_vprintk);
  129. static __init int init_trace_printk(void)
  130. {
  131. return register_module_notifier(&module_trace_bprintk_format_nb);
  132. }
  133. early_initcall(init_trace_printk);