2 * Copyright (C) 2008 Pekka Enberg, Eduard - Gabriel Munteanu
4 * This file is released under GPL version 2.
7 #include <linux/string.h>
8 #include <linux/debugfs.h>
9 #include <linux/relay.h>
10 #include <linux/module.h>
11 #include <linux/marker.h>
12 #include <linux/gfp.h>
13 #include <trace/kmemtrace.h>
15 #define KMEMTRACE_SUBBUF_SIZE 524288
16 #define KMEMTRACE_DEF_N_SUBBUFS 20
18 static struct rchan *kmemtrace_chan;
19 static u32 kmemtrace_buf_overruns;
21 static unsigned int kmemtrace_n_subbufs;
23 /* disabled by default */
24 static unsigned int kmemtrace_enabled;
27 * The sequence number is used for reordering kmemtrace packets
28 * in userspace, since they are logged as per-CPU data.
30 * atomic_t should always be a 32-bit signed integer. Wraparound is not
31 * likely to occur, but userspace can deal with it by expecting a certain
32 * sequence number in the next packet that will be read.
34 static atomic_t kmemtrace_seq_num;
36 #define KMEMTRACE_ABI_VERSION 1
38 static u32 kmemtrace_abi_version __read_mostly = KMEMTRACE_ABI_VERSION;
40 enum kmemtrace_event_id {
41 KMEMTRACE_EVENT_ALLOC = 0,
45 struct kmemtrace_event {
52 } __attribute__ ((__packed__));
54 struct kmemtrace_stats_alloc {
59 } __attribute__ ((__packed__));
61 static void kmemtrace_probe_alloc(void *probe_data, void *call_data,
62 const char *format, va_list *args)
65 struct kmemtrace_event *ev;
66 struct kmemtrace_stats_alloc *stats;
69 local_irq_save(flags);
71 buf = relay_reserve(kmemtrace_chan,
72 sizeof(struct kmemtrace_event) +
73 sizeof(struct kmemtrace_stats_alloc));
78 * Don't convert this to use structure initializers,
79 * C99 does not guarantee the rvalues evaluation order.
83 ev->event_id = KMEMTRACE_EVENT_ALLOC;
84 ev->type_id = va_arg(*args, int);
85 ev->event_size = sizeof(struct kmemtrace_event) +
86 sizeof(struct kmemtrace_stats_alloc);
87 ev->seq_num = atomic_add_return(1, &kmemtrace_seq_num);
88 ev->call_site = va_arg(*args, unsigned long);
89 ev->ptr = va_arg(*args, unsigned long);
91 stats = buf + sizeof(struct kmemtrace_event);
92 stats->bytes_req = va_arg(*args, unsigned long);
93 stats->bytes_alloc = va_arg(*args, unsigned long);
94 stats->gfp_flags = va_arg(*args, unsigned long);
95 stats->numa_node = va_arg(*args, int);
98 local_irq_restore(flags);
101 static void kmemtrace_probe_free(void *probe_data, void *call_data,
102 const char *format, va_list *args)
105 struct kmemtrace_event *ev;
107 local_irq_save(flags);
109 ev = relay_reserve(kmemtrace_chan, sizeof(struct kmemtrace_event));
114 * Don't convert this to use structure initializers,
115 * C99 does not guarantee the rvalues evaluation order.
117 ev->event_id = KMEMTRACE_EVENT_FREE;
118 ev->type_id = va_arg(*args, int);
119 ev->event_size = sizeof(struct kmemtrace_event);
120 ev->seq_num = atomic_add_return(1, &kmemtrace_seq_num);
121 ev->call_site = va_arg(*args, unsigned long);
122 ev->ptr = va_arg(*args, unsigned long);
125 local_irq_restore(flags);
128 static struct dentry *
129 kmemtrace_create_buf_file(const char *filename, struct dentry *parent,
130 int mode, struct rchan_buf *buf, int *is_global)
132 return debugfs_create_file(filename, mode, parent, buf,
133 &relay_file_operations);
136 static int kmemtrace_remove_buf_file(struct dentry *dentry)
138 debugfs_remove(dentry);
143 static int kmemtrace_subbuf_start(struct rchan_buf *buf,
148 if (relay_buf_full(buf)) {
150 * We know it's not SMP-safe, but neither
151 * debugfs_create_u32() is.
153 kmemtrace_buf_overruns++;
160 static struct rchan_callbacks relay_callbacks = {
161 .create_buf_file = kmemtrace_create_buf_file,
162 .remove_buf_file = kmemtrace_remove_buf_file,
163 .subbuf_start = kmemtrace_subbuf_start,
166 static struct dentry *kmemtrace_dir;
167 static struct dentry *kmemtrace_overruns_dentry;
168 static struct dentry *kmemtrace_abi_version_dentry;
170 static struct dentry *kmemtrace_enabled_dentry;
172 static int kmemtrace_start_probes(void)
176 err = marker_probe_register("kmemtrace_alloc", "type_id %d "
177 "call_site %lu ptr %lu "
178 "bytes_req %lu bytes_alloc %lu "
179 "gfp_flags %lu node %d",
180 kmemtrace_probe_alloc, NULL);
183 err = marker_probe_register("kmemtrace_free", "type_id %d "
184 "call_site %lu ptr %lu",
185 kmemtrace_probe_free, NULL);
190 static void kmemtrace_stop_probes(void)
192 marker_probe_unregister("kmemtrace_alloc",
193 kmemtrace_probe_alloc, NULL);
194 marker_probe_unregister("kmemtrace_free",
195 kmemtrace_probe_free, NULL);
198 static int kmemtrace_enabled_get(void *data, u64 *val)
200 *val = *((int *) data);
205 static int kmemtrace_enabled_set(void *data, u64 val)
207 u64 old_val = kmemtrace_enabled;
209 *((int *) data) = !!val;
214 kmemtrace_start_probes();
216 kmemtrace_stop_probes();
221 DEFINE_SIMPLE_ATTRIBUTE(kmemtrace_enabled_fops,
222 kmemtrace_enabled_get,
223 kmemtrace_enabled_set, "%llu\n");
225 static void kmemtrace_cleanup(void)
227 if (kmemtrace_enabled_dentry)
228 debugfs_remove(kmemtrace_enabled_dentry);
230 kmemtrace_stop_probes();
232 if (kmemtrace_abi_version_dentry)
233 debugfs_remove(kmemtrace_abi_version_dentry);
234 if (kmemtrace_overruns_dentry)
235 debugfs_remove(kmemtrace_overruns_dentry);
237 relay_close(kmemtrace_chan);
238 kmemtrace_chan = NULL;
241 debugfs_remove(kmemtrace_dir);
244 static int __init kmemtrace_setup_late(void)
249 kmemtrace_dir = debugfs_create_dir("kmemtrace", NULL);
253 kmemtrace_abi_version_dentry =
254 debugfs_create_u32("abi_version", S_IRUSR,
255 kmemtrace_dir, &kmemtrace_abi_version);
256 kmemtrace_overruns_dentry =
257 debugfs_create_u32("total_overruns", S_IRUSR,
258 kmemtrace_dir, &kmemtrace_buf_overruns);
259 if (!kmemtrace_overruns_dentry || !kmemtrace_abi_version_dentry)
262 kmemtrace_enabled_dentry =
263 debugfs_create_file("enabled", S_IRUSR | S_IWUSR,
264 kmemtrace_dir, &kmemtrace_enabled,
265 &kmemtrace_enabled_fops);
266 if (!kmemtrace_enabled_dentry)
269 if (relay_late_setup_files(kmemtrace_chan, "cpu", kmemtrace_dir))
272 printk(KERN_INFO "kmemtrace: fully up.\n");
281 late_initcall(kmemtrace_setup_late);
283 static int __init kmemtrace_set_boot_enabled(char *str)
288 if (!strcmp(str, "yes"))
289 kmemtrace_enabled = 1;
290 else if (!strcmp(str, "no"))
291 kmemtrace_enabled = 0;
297 early_param("kmemtrace.enable", kmemtrace_set_boot_enabled);
299 static int __init kmemtrace_set_subbufs(char *str)
301 get_option(&str, &kmemtrace_n_subbufs);
304 early_param("kmemtrace.subbufs", kmemtrace_set_subbufs);
306 void kmemtrace_init(void)
308 if (!kmemtrace_n_subbufs)
309 kmemtrace_n_subbufs = KMEMTRACE_DEF_N_SUBBUFS;
311 kmemtrace_chan = relay_open(NULL, NULL, KMEMTRACE_SUBBUF_SIZE,
312 kmemtrace_n_subbufs, &relay_callbacks,
314 if (!kmemtrace_chan) {
315 printk(KERN_ERR "kmemtrace: could not open relay channel.\n");
319 if (!kmemtrace_enabled) {
320 printk(KERN_INFO "kmemtrace: disabled. Pass "
321 "kemtrace.enable=yes as kernel parameter for "
322 "boot-time tracing.\n");
325 if (kmemtrace_start_probes()) {
326 printk(KERN_ERR "kmemtrace: could not register marker probes!\n");
331 printk(KERN_INFO "kmemtrace: enabled.\n");