kmemtrace.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /*
  2. * Copyright (C) 2008 Pekka Enberg, Eduard - Gabriel Munteanu
  3. *
  4. * This file is released under GPL version 2.
  5. */
  6. #include <linux/string.h>
  7. #include <linux/debugfs.h>
  8. #include <linux/relay.h>
  9. #include <linux/module.h>
  10. #include <linux/marker.h>
  11. #include <linux/gfp.h>
  12. #include <linux/kmemtrace.h>
  13. #define KMEMTRACE_SUBBUF_SIZE 524288
  14. #define KMEMTRACE_DEF_N_SUBBUFS 20
  15. static struct rchan *kmemtrace_chan;
  16. static u32 kmemtrace_buf_overruns;
  17. static unsigned int kmemtrace_n_subbufs;
  18. /* disabled by default */
  19. static unsigned int kmemtrace_enabled;
  20. /*
  21. * The sequence number is used for reordering kmemtrace packets
  22. * in userspace, since they are logged as per-CPU data.
  23. *
  24. * atomic_t should always be a 32-bit signed integer. Wraparound is not
  25. * likely to occur, but userspace can deal with it by expecting a certain
  26. * sequence number in the next packet that will be read.
  27. */
  28. static atomic_t kmemtrace_seq_num;
  29. #define KMEMTRACE_ABI_VERSION 1
  30. static u32 kmemtrace_abi_version __read_mostly = KMEMTRACE_ABI_VERSION;
  31. enum kmemtrace_event_id {
  32. KMEMTRACE_EVENT_ALLOC = 0,
  33. KMEMTRACE_EVENT_FREE,
  34. };
  35. struct kmemtrace_event {
  36. u8 event_id;
  37. u8 type_id;
  38. u16 event_size;
  39. s32 seq_num;
  40. u64 call_site;
  41. u64 ptr;
  42. } __attribute__ ((__packed__));
  43. struct kmemtrace_stats_alloc {
  44. u64 bytes_req;
  45. u64 bytes_alloc;
  46. u32 gfp_flags;
  47. s32 numa_node;
  48. } __attribute__ ((__packed__));
  49. static void kmemtrace_probe_alloc(void *probe_data, void *call_data,
  50. const char *format, va_list *args)
  51. {
  52. unsigned long flags;
  53. struct kmemtrace_event *ev;
  54. struct kmemtrace_stats_alloc *stats;
  55. void *buf;
  56. local_irq_save(flags);
  57. buf = relay_reserve(kmemtrace_chan,
  58. sizeof(struct kmemtrace_event) +
  59. sizeof(struct kmemtrace_stats_alloc));
  60. if (!buf)
  61. goto failed;
  62. /*
  63. * Don't convert this to use structure initializers,
  64. * C99 does not guarantee the rvalues evaluation order.
  65. */
  66. ev = buf;
  67. ev->event_id = KMEMTRACE_EVENT_ALLOC;
  68. ev->type_id = va_arg(*args, int);
  69. ev->event_size = sizeof(struct kmemtrace_event) +
  70. sizeof(struct kmemtrace_stats_alloc);
  71. ev->seq_num = atomic_add_return(1, &kmemtrace_seq_num);
  72. ev->call_site = va_arg(*args, unsigned long);
  73. ev->ptr = va_arg(*args, unsigned long);
  74. stats = buf + sizeof(struct kmemtrace_event);
  75. stats->bytes_req = va_arg(*args, unsigned long);
  76. stats->bytes_alloc = va_arg(*args, unsigned long);
  77. stats->gfp_flags = va_arg(*args, unsigned long);
  78. stats->numa_node = va_arg(*args, int);
  79. failed:
  80. local_irq_restore(flags);
  81. }
  82. static void kmemtrace_probe_free(void *probe_data, void *call_data,
  83. const char *format, va_list *args)
  84. {
  85. unsigned long flags;
  86. struct kmemtrace_event *ev;
  87. local_irq_save(flags);
  88. ev = relay_reserve(kmemtrace_chan, sizeof(struct kmemtrace_event));
  89. if (!ev)
  90. goto failed;
  91. /*
  92. * Don't convert this to use structure initializers,
  93. * C99 does not guarantee the rvalues evaluation order.
  94. */
  95. ev->event_id = KMEMTRACE_EVENT_FREE;
  96. ev->type_id = va_arg(*args, int);
  97. ev->event_size = sizeof(struct kmemtrace_event);
  98. ev->seq_num = atomic_add_return(1, &kmemtrace_seq_num);
  99. ev->call_site = va_arg(*args, unsigned long);
  100. ev->ptr = va_arg(*args, unsigned long);
  101. failed:
  102. local_irq_restore(flags);
  103. }
  104. static struct dentry *
  105. kmemtrace_create_buf_file(const char *filename, struct dentry *parent,
  106. int mode, struct rchan_buf *buf, int *is_global)
  107. {
  108. return debugfs_create_file(filename, mode, parent, buf,
  109. &relay_file_operations);
  110. }
  111. static int kmemtrace_remove_buf_file(struct dentry *dentry)
  112. {
  113. debugfs_remove(dentry);
  114. return 0;
  115. }
  116. static int kmemtrace_subbuf_start(struct rchan_buf *buf,
  117. void *subbuf,
  118. void *prev_subbuf,
  119. size_t prev_padding)
  120. {
  121. if (relay_buf_full(buf)) {
  122. /*
  123. * We know it's not SMP-safe, but neither
  124. * debugfs_create_u32() is.
  125. */
  126. kmemtrace_buf_overruns++;
  127. return 0;
  128. }
  129. return 1;
  130. }
  131. static struct rchan_callbacks relay_callbacks = {
  132. .create_buf_file = kmemtrace_create_buf_file,
  133. .remove_buf_file = kmemtrace_remove_buf_file,
  134. .subbuf_start = kmemtrace_subbuf_start,
  135. };
  136. static struct dentry *kmemtrace_dir;
  137. static struct dentry *kmemtrace_overruns_dentry;
  138. static struct dentry *kmemtrace_abi_version_dentry;
  139. static struct dentry *kmemtrace_enabled_dentry;
  140. static int kmemtrace_start_probes(void)
  141. {
  142. int err;
  143. err = marker_probe_register("kmemtrace_alloc", "type_id %d "
  144. "call_site %lu ptr %lu "
  145. "bytes_req %lu bytes_alloc %lu "
  146. "gfp_flags %lu node %d",
  147. kmemtrace_probe_alloc, NULL);
  148. if (err)
  149. return err;
  150. err = marker_probe_register("kmemtrace_free", "type_id %d "
  151. "call_site %lu ptr %lu",
  152. kmemtrace_probe_free, NULL);
  153. return err;
  154. }
  155. static void kmemtrace_stop_probes(void)
  156. {
  157. marker_probe_unregister("kmemtrace_alloc",
  158. kmemtrace_probe_alloc, NULL);
  159. marker_probe_unregister("kmemtrace_free",
  160. kmemtrace_probe_free, NULL);
  161. }
  162. static int kmemtrace_enabled_get(void *data, u64 *val)
  163. {
  164. *val = *((int *) data);
  165. return 0;
  166. }
  167. static int kmemtrace_enabled_set(void *data, u64 val)
  168. {
  169. u64 old_val = kmemtrace_enabled;
  170. *((int *) data) = !!val;
  171. if (old_val == val)
  172. return 0;
  173. if (val)
  174. kmemtrace_start_probes();
  175. else
  176. kmemtrace_stop_probes();
  177. return 0;
  178. }
  179. DEFINE_SIMPLE_ATTRIBUTE(kmemtrace_enabled_fops,
  180. kmemtrace_enabled_get,
  181. kmemtrace_enabled_set, "%llu\n");
  182. static void kmemtrace_cleanup(void)
  183. {
  184. if (kmemtrace_enabled_dentry)
  185. debugfs_remove(kmemtrace_enabled_dentry);
  186. kmemtrace_stop_probes();
  187. if (kmemtrace_abi_version_dentry)
  188. debugfs_remove(kmemtrace_abi_version_dentry);
  189. if (kmemtrace_overruns_dentry)
  190. debugfs_remove(kmemtrace_overruns_dentry);
  191. relay_close(kmemtrace_chan);
  192. kmemtrace_chan = NULL;
  193. if (kmemtrace_dir)
  194. debugfs_remove(kmemtrace_dir);
  195. }
  196. static int __init kmemtrace_setup_late(void)
  197. {
  198. if (!kmemtrace_chan)
  199. goto failed;
  200. kmemtrace_dir = debugfs_create_dir("kmemtrace", NULL);
  201. if (!kmemtrace_dir)
  202. goto cleanup;
  203. kmemtrace_abi_version_dentry =
  204. debugfs_create_u32("abi_version", S_IRUSR,
  205. kmemtrace_dir, &kmemtrace_abi_version);
  206. kmemtrace_overruns_dentry =
  207. debugfs_create_u32("total_overruns", S_IRUSR,
  208. kmemtrace_dir, &kmemtrace_buf_overruns);
  209. if (!kmemtrace_overruns_dentry || !kmemtrace_abi_version_dentry)
  210. goto cleanup;
  211. kmemtrace_enabled_dentry =
  212. debugfs_create_file("enabled", S_IRUSR | S_IWUSR,
  213. kmemtrace_dir, &kmemtrace_enabled,
  214. &kmemtrace_enabled_fops);
  215. if (!kmemtrace_enabled_dentry)
  216. goto cleanup;
  217. if (relay_late_setup_files(kmemtrace_chan, "cpu", kmemtrace_dir))
  218. goto cleanup;
  219. printk(KERN_INFO "kmemtrace: fully up.\n");
  220. return 0;
  221. cleanup:
  222. kmemtrace_cleanup();
  223. failed:
  224. return 1;
  225. }
  226. late_initcall(kmemtrace_setup_late);
  227. static int __init kmemtrace_set_boot_enabled(char *str)
  228. {
  229. if (!str)
  230. return -EINVAL;
  231. if (!strcmp(str, "yes"))
  232. kmemtrace_enabled = 1;
  233. else if (!strcmp(str, "no"))
  234. kmemtrace_enabled = 0;
  235. else
  236. return -EINVAL;
  237. return 0;
  238. }
  239. early_param("kmemtrace.enable", kmemtrace_set_boot_enabled);
  240. static int __init kmemtrace_set_subbufs(char *str)
  241. {
  242. get_option(&str, &kmemtrace_n_subbufs);
  243. return 0;
  244. }
  245. early_param("kmemtrace.subbufs", kmemtrace_set_subbufs);
  246. void kmemtrace_init(void)
  247. {
  248. if (!kmemtrace_n_subbufs)
  249. kmemtrace_n_subbufs = KMEMTRACE_DEF_N_SUBBUFS;
  250. kmemtrace_chan = relay_open(NULL, NULL, KMEMTRACE_SUBBUF_SIZE,
  251. kmemtrace_n_subbufs, &relay_callbacks,
  252. NULL);
  253. if (!kmemtrace_chan) {
  254. printk(KERN_ERR "kmemtrace: could not open relay channel.\n");
  255. return;
  256. }
  257. if (!kmemtrace_enabled) {
  258. printk(KERN_INFO "kmemtrace: disabled. Pass "
  259. "kemtrace.enable=yes as kernel parameter for "
  260. "boot-time tracing.");
  261. return;
  262. }
  263. if (kmemtrace_start_probes()) {
  264. printk(KERN_ERR "kmemtrace: could not register marker probes!\n");
  265. kmemtrace_cleanup();
  266. return;
  267. }
  268. printk(KERN_INFO "kmemtrace: enabled.\n");
  269. }