aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/kmemtrace.c206
-rw-r--r--kernel/trace/trace.h6
2 files changed, 151 insertions, 61 deletions
diff --git a/kernel/trace/kmemtrace.c b/kernel/trace/kmemtrace.c
index ae201b3eda89..4f7b5db5dd06 100644
--- a/kernel/trace/kmemtrace.c
+++ b/kernel/trace/kmemtrace.c
@@ -10,6 +10,7 @@
10#include <linux/debugfs.h> 10#include <linux/debugfs.h>
11#include <linux/fs.h> 11#include <linux/fs.h>
12#include <linux/seq_file.h> 12#include <linux/seq_file.h>
13#include <linux/tracepoint.h>
13#include <trace/kmemtrace.h> 14#include <trace/kmemtrace.h>
14 15
15#include "trace.h" 16#include "trace.h"
@@ -29,10 +30,150 @@ static struct tracer_flags kmem_tracer_flags = {
29 .opts = kmem_opts 30 .opts = kmem_opts
30}; 31};
31 32
32
33static bool kmem_tracing_enabled __read_mostly;
34static struct trace_array *kmemtrace_array; 33static struct trace_array *kmemtrace_array;
35 34
35/* Trace allocations */
36static inline void kmemtrace_alloc(enum kmemtrace_type_id type_id,
37 unsigned long call_site,
38 const void *ptr,
39 size_t bytes_req,
40 size_t bytes_alloc,
41 gfp_t gfp_flags,
42 int node)
43{
44 struct ring_buffer_event *event;
45 struct kmemtrace_alloc_entry *entry;
46 struct trace_array *tr = kmemtrace_array;
47
48 event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry));
49 if (!event)
50 return;
51 entry = ring_buffer_event_data(event);
52 tracing_generic_entry_update(&entry->ent, 0, 0);
53
54 entry->ent.type = TRACE_KMEM_ALLOC;
55 entry->call_site = call_site;
56 entry->ptr = ptr;
57 entry->bytes_req = bytes_req;
58 entry->bytes_alloc = bytes_alloc;
59 entry->gfp_flags = gfp_flags;
60 entry->node = node;
61
62 ring_buffer_unlock_commit(tr->buffer, event);
63
64 trace_wake_up();
65}
66
67static inline void kmemtrace_free(enum kmemtrace_type_id type_id,
68 unsigned long call_site,
69 const void *ptr)
70{
71 struct ring_buffer_event *event;
72 struct kmemtrace_free_entry *entry;
73 struct trace_array *tr = kmemtrace_array;
74
75 event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry));
76 if (!event)
77 return;
78 entry = ring_buffer_event_data(event);
79 tracing_generic_entry_update(&entry->ent, 0, 0);
80
81 entry->ent.type = TRACE_KMEM_FREE;
82 entry->type_id = type_id;
83 entry->call_site = call_site;
84 entry->ptr = ptr;
85
86 ring_buffer_unlock_commit(tr->buffer, event);
87
88 trace_wake_up();
89}
90
91static void kmemtrace_kmalloc(unsigned long call_site,
92 const void *ptr,
93 size_t bytes_req,
94 size_t bytes_alloc,
95 gfp_t gfp_flags)
96{
97 kmemtrace_alloc(KMEMTRACE_TYPE_KMALLOC, call_site, ptr,
98 bytes_req, bytes_alloc, gfp_flags, -1);
99}
100
101static void kmemtrace_kmem_cache_alloc(unsigned long call_site,
102 const void *ptr,
103 size_t bytes_req,
104 size_t bytes_alloc,
105 gfp_t gfp_flags)
106{
107 kmemtrace_alloc(KMEMTRACE_TYPE_CACHE, call_site, ptr,
108 bytes_req, bytes_alloc, gfp_flags, -1);
109}
110
111static void kmemtrace_kmalloc_node(unsigned long call_site,
112 const void *ptr,
113 size_t bytes_req,
114 size_t bytes_alloc,
115 gfp_t gfp_flags,
116 int node)
117{
118 kmemtrace_alloc(KMEMTRACE_TYPE_KMALLOC, call_site, ptr,
119 bytes_req, bytes_alloc, gfp_flags, node);
120}
121
122static void kmemtrace_kmem_cache_alloc_node(unsigned long call_site,
123 const void *ptr,
124 size_t bytes_req,
125 size_t bytes_alloc,
126 gfp_t gfp_flags,
127 int node)
128{
129 kmemtrace_alloc(KMEMTRACE_TYPE_CACHE, call_site, ptr,
130 bytes_req, bytes_alloc, gfp_flags, node);
131}
132
133static void kmemtrace_kfree(unsigned long call_site, const void *ptr)
134{
135 kmemtrace_free(KMEMTRACE_TYPE_KMALLOC, call_site, ptr);
136}
137
138static void kmemtrace_kmem_cache_free(unsigned long call_site, const void *ptr)
139{
140 kmemtrace_free(KMEMTRACE_TYPE_CACHE, call_site, ptr);
141}
142
143static int kmemtrace_start_probes(void)
144{
145 int err;
146
147 err = register_trace_kmalloc(kmemtrace_kmalloc);
148 if (err)
149 return err;
150 err = register_trace_kmem_cache_alloc(kmemtrace_kmem_cache_alloc);
151 if (err)
152 return err;
153 err = register_trace_kmalloc_node(kmemtrace_kmalloc_node);
154 if (err)
155 return err;
156 err = register_trace_kmem_cache_alloc_node(kmemtrace_kmem_cache_alloc_node);
157 if (err)
158 return err;
159 err = register_trace_kfree(kmemtrace_kfree);
160 if (err)
161 return err;
162 err = register_trace_kmem_cache_free(kmemtrace_kmem_cache_free);
163
164 return err;
165}
166
167static void kmemtrace_stop_probes(void)
168{
169 unregister_trace_kmalloc(kmemtrace_kmalloc);
170 unregister_trace_kmem_cache_alloc(kmemtrace_kmem_cache_alloc);
171 unregister_trace_kmalloc_node(kmemtrace_kmalloc_node);
172 unregister_trace_kmem_cache_alloc_node(kmemtrace_kmem_cache_alloc_node);
173 unregister_trace_kfree(kmemtrace_kfree);
174 unregister_trace_kmem_cache_free(kmemtrace_kmem_cache_free);
175}
176
36static int kmem_trace_init(struct trace_array *tr) 177static int kmem_trace_init(struct trace_array *tr)
37{ 178{
38 int cpu; 179 int cpu;
@@ -41,14 +182,14 @@ static int kmem_trace_init(struct trace_array *tr)
41 for_each_cpu_mask(cpu, cpu_possible_map) 182 for_each_cpu_mask(cpu, cpu_possible_map)
42 tracing_reset(tr, cpu); 183 tracing_reset(tr, cpu);
43 184
44 kmem_tracing_enabled = true; 185 kmemtrace_start_probes();
45 186
46 return 0; 187 return 0;
47} 188}
48 189
49static void kmem_trace_reset(struct trace_array *tr) 190static void kmem_trace_reset(struct trace_array *tr)
50{ 191{
51 kmem_tracing_enabled = false; 192 kmemtrace_stop_probes();
52} 193}
53 194
54static void kmemtrace_headers(struct seq_file *s) 195static void kmemtrace_headers(struct seq_file *s)
@@ -260,63 +401,6 @@ static enum print_line_t kmemtrace_print_line(struct trace_iterator *iter)
260 } 401 }
261} 402}
262 403
263/* Trace allocations */
264void kmemtrace_mark_alloc_node(enum kmemtrace_type_id type_id,
265 unsigned long call_site,
266 const void *ptr,
267 size_t bytes_req,
268 size_t bytes_alloc,
269 gfp_t gfp_flags,
270 int node)
271{
272 struct ring_buffer_event *event;
273 struct kmemtrace_alloc_entry *entry;
274 struct trace_array *tr = kmemtrace_array;
275
276 if (!kmem_tracing_enabled)
277 return;
278
279 event = trace_buffer_lock_reserve(tr, TRACE_KMEM_ALLOC,
280 sizeof(*entry), 0, 0);
281 if (!event)
282 return;
283 entry = ring_buffer_event_data(event);
284
285 entry->call_site = call_site;
286 entry->ptr = ptr;
287 entry->bytes_req = bytes_req;
288 entry->bytes_alloc = bytes_alloc;
289 entry->gfp_flags = gfp_flags;
290 entry->node = node;
291
292 trace_buffer_unlock_commit(tr, event, 0, 0);
293}
294EXPORT_SYMBOL(kmemtrace_mark_alloc_node);
295
296void kmemtrace_mark_free(enum kmemtrace_type_id type_id,
297 unsigned long call_site,
298 const void *ptr)
299{
300 struct ring_buffer_event *event;
301 struct kmemtrace_free_entry *entry;
302 struct trace_array *tr = kmemtrace_array;
303
304 if (!kmem_tracing_enabled)
305 return;
306
307 event = trace_buffer_lock_reserve(tr, TRACE_KMEM_FREE,
308 sizeof(*entry), 0, 0);
309 if (!event)
310 return;
311 entry = ring_buffer_event_data(event);
312 entry->type_id = type_id;
313 entry->call_site = call_site;
314 entry->ptr = ptr;
315
316 trace_buffer_unlock_commit(tr, event, 0, 0);
317}
318EXPORT_SYMBOL(kmemtrace_mark_free);
319
320static struct tracer kmem_tracer __read_mostly = { 404static struct tracer kmem_tracer __read_mostly = {
321 .name = "kmemtrace", 405 .name = "kmemtrace",
322 .init = kmem_trace_init, 406 .init = kmem_trace_init,
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index cb0ce3fc36d3..cbc168f1e43d 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -182,6 +182,12 @@ struct trace_power {
182 struct power_trace state_data; 182 struct power_trace state_data;
183}; 183};
184 184
185enum kmemtrace_type_id {
186 KMEMTRACE_TYPE_KMALLOC = 0, /* kmalloc() or kfree(). */
187 KMEMTRACE_TYPE_CACHE, /* kmem_cache_*(). */
188 KMEMTRACE_TYPE_PAGES, /* __get_free_pages() and friends. */
189};
190
185struct kmemtrace_alloc_entry { 191struct kmemtrace_alloc_entry {
186 struct trace_entry ent; 192 struct trace_entry ent;
187 enum kmemtrace_type_id type_id; 193 enum kmemtrace_type_id type_id;