PageRenderTime 52ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/kernel/trace/trace_printk.c

https://github.com/Dabary/linux_gt-i9000
C | 251 lines | 193 code | 44 blank | 14 comment | 17 complexity | 8cc4b3650f74d2f4c6536b6051c05ecb MD5 | raw file
  1. /*
  2. * trace binary printk
  3. *
  4. * Copyright (C) 2008 Lai Jiangshan <laijs@cn.fujitsu.com>
  5. *
  6. */
  7. #include <linux/seq_file.h>
  8. #include <linux/debugfs.h>
  9. #include <linux/uaccess.h>
  10. #include <linux/kernel.h>
  11. #include <linux/ftrace.h>
  12. #include <linux/string.h>
  13. #include <linux/module.h>
  14. #include <linux/mutex.h>
  15. #include <linux/ctype.h>
  16. #include <linux/list.h>
  17. #include <linux/slab.h>
  18. #include <linux/fs.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, 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, 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, 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, fmt, ap);
  127. }
  128. EXPORT_SYMBOL_GPL(__ftrace_vprintk);
  129. static void *
  130. t_start(struct seq_file *m, loff_t *pos)
  131. {
  132. const char **fmt = __start___trace_bprintk_fmt + *pos;
  133. if ((unsigned long)fmt >= (unsigned long)__stop___trace_bprintk_fmt)
  134. return NULL;
  135. return fmt;
  136. }
  137. static void *t_next(struct seq_file *m, void * v, loff_t *pos)
  138. {
  139. (*pos)++;
  140. return t_start(m, pos);
  141. }
  142. static int t_show(struct seq_file *m, void *v)
  143. {
  144. const char **fmt = v;
  145. const char *str = *fmt;
  146. int i;
  147. seq_printf(m, "0x%lx : \"", *(unsigned long *)fmt);
  148. /*
  149. * Tabs and new lines need to be converted.
  150. */
  151. for (i = 0; str[i]; i++) {
  152. switch (str[i]) {
  153. case '\n':
  154. seq_puts(m, "\\n");
  155. break;
  156. case '\t':
  157. seq_puts(m, "\\t");
  158. break;
  159. case '\\':
  160. seq_puts(m, "\\");
  161. break;
  162. case '"':
  163. seq_puts(m, "\\\"");
  164. break;
  165. default:
  166. seq_putc(m, str[i]);
  167. }
  168. }
  169. seq_puts(m, "\"\n");
  170. return 0;
  171. }
  172. static void t_stop(struct seq_file *m, void *p)
  173. {
  174. }
  175. static const struct seq_operations show_format_seq_ops = {
  176. .start = t_start,
  177. .next = t_next,
  178. .show = t_show,
  179. .stop = t_stop,
  180. };
  181. static int
  182. ftrace_formats_open(struct inode *inode, struct file *file)
  183. {
  184. return seq_open(file, &show_format_seq_ops);
  185. }
  186. static const struct file_operations ftrace_formats_fops = {
  187. .open = ftrace_formats_open,
  188. .read = seq_read,
  189. .llseek = seq_lseek,
  190. .release = seq_release,
  191. };
  192. static __init int init_trace_printk_function_export(void)
  193. {
  194. struct dentry *d_tracer;
  195. d_tracer = tracing_init_dentry();
  196. if (!d_tracer)
  197. return 0;
  198. trace_create_file("printk_formats", 0444, d_tracer,
  199. NULL, &ftrace_formats_fops);
  200. return 0;
  201. }
  202. fs_initcall(init_trace_printk_function_export);
  203. static __init int init_trace_printk(void)
  204. {
  205. return register_module_notifier(&module_trace_bprintk_format_nb);
  206. }
  207. early_initcall(init_trace_printk);