|
@@ -239,12 +239,52 @@ struct kmemtrace_user_event_alloc {
|
|
|
};
|
|
|
|
|
|
static enum print_line_t
|
|
|
-kmemtrace_print_alloc_user(struct trace_iterator *iter,
|
|
|
- struct kmemtrace_alloc_entry *entry)
|
|
|
+kmemtrace_print_alloc_user(struct trace_iterator *iter, int flags)
|
|
|
+{
|
|
|
+ struct trace_seq *s = &iter->seq;
|
|
|
+ struct kmemtrace_alloc_entry *entry;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ trace_assign_type(entry, iter->ent);
|
|
|
+
|
|
|
+ ret = trace_seq_printf(s, "type_id %d call_site %pF ptr %lu "
|
|
|
+ "bytes_req %lu bytes_alloc %lu gfp_flags %lu node %d\n",
|
|
|
+ entry->type_id, (void *)entry->call_site, (unsigned long)entry->ptr,
|
|
|
+ (unsigned long)entry->bytes_req, (unsigned long)entry->bytes_alloc,
|
|
|
+ (unsigned long)entry->gfp_flags, entry->node);
|
|
|
+
|
|
|
+ if (!ret)
|
|
|
+ return TRACE_TYPE_PARTIAL_LINE;
|
|
|
+ return TRACE_TYPE_HANDLED;
|
|
|
+}
|
|
|
+
|
|
|
+static enum print_line_t
|
|
|
+kmemtrace_print_free_user(struct trace_iterator *iter, int flags)
|
|
|
{
|
|
|
- struct kmemtrace_user_event_alloc *ev_alloc;
|
|
|
struct trace_seq *s = &iter->seq;
|
|
|
+ struct kmemtrace_free_entry *entry;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ trace_assign_type(entry, iter->ent);
|
|
|
+
|
|
|
+ ret = trace_seq_printf(s, "type_id %d call_site %pF ptr %lu\n",
|
|
|
+ entry->type_id, (void *)entry->call_site,
|
|
|
+ (unsigned long)entry->ptr);
|
|
|
+
|
|
|
+ if (!ret)
|
|
|
+ return TRACE_TYPE_PARTIAL_LINE;
|
|
|
+ return TRACE_TYPE_HANDLED;
|
|
|
+}
|
|
|
+
|
|
|
+static enum print_line_t
|
|
|
+kmemtrace_print_alloc_user_bin(struct trace_iterator *iter, int flags)
|
|
|
+{
|
|
|
+ struct trace_seq *s = &iter->seq;
|
|
|
+ struct kmemtrace_alloc_entry *entry;
|
|
|
struct kmemtrace_user_event *ev;
|
|
|
+ struct kmemtrace_user_event_alloc *ev_alloc;
|
|
|
+
|
|
|
+ trace_assign_type(entry, iter->ent);
|
|
|
|
|
|
ev = trace_seq_reserve(s, sizeof(*ev));
|
|
|
if (!ev)
|
|
@@ -271,12 +311,14 @@ kmemtrace_print_alloc_user(struct trace_iterator *iter,
|
|
|
}
|
|
|
|
|
|
static enum print_line_t
|
|
|
-kmemtrace_print_free_user(struct trace_iterator *iter,
|
|
|
- struct kmemtrace_free_entry *entry)
|
|
|
+kmemtrace_print_free_user_bin(struct trace_iterator *iter, int flags)
|
|
|
{
|
|
|
struct trace_seq *s = &iter->seq;
|
|
|
+ struct kmemtrace_free_entry *entry;
|
|
|
struct kmemtrace_user_event *ev;
|
|
|
|
|
|
+ trace_assign_type(entry, iter->ent);
|
|
|
+
|
|
|
ev = trace_seq_reserve(s, sizeof(*ev));
|
|
|
if (!ev)
|
|
|
return TRACE_TYPE_PARTIAL_LINE;
|
|
@@ -294,12 +336,14 @@ kmemtrace_print_free_user(struct trace_iterator *iter,
|
|
|
|
|
|
/* The two other following provide a more minimalistic output */
|
|
|
static enum print_line_t
|
|
|
-kmemtrace_print_alloc_compress(struct trace_iterator *iter,
|
|
|
- struct kmemtrace_alloc_entry *entry)
|
|
|
+kmemtrace_print_alloc_compress(struct trace_iterator *iter)
|
|
|
{
|
|
|
+ struct kmemtrace_alloc_entry *entry;
|
|
|
struct trace_seq *s = &iter->seq;
|
|
|
int ret;
|
|
|
|
|
|
+ trace_assign_type(entry, iter->ent);
|
|
|
+
|
|
|
/* Alloc entry */
|
|
|
ret = trace_seq_printf(s, " + ");
|
|
|
if (!ret)
|
|
@@ -362,12 +406,14 @@ kmemtrace_print_alloc_compress(struct trace_iterator *iter,
|
|
|
}
|
|
|
|
|
|
static enum print_line_t
|
|
|
-kmemtrace_print_free_compress(struct trace_iterator *iter,
|
|
|
- struct kmemtrace_free_entry *entry)
|
|
|
+kmemtrace_print_free_compress(struct trace_iterator *iter)
|
|
|
{
|
|
|
+ struct kmemtrace_free_entry *entry;
|
|
|
struct trace_seq *s = &iter->seq;
|
|
|
int ret;
|
|
|
|
|
|
+ trace_assign_type(entry, iter->ent);
|
|
|
+
|
|
|
/* Free entry */
|
|
|
ret = trace_seq_printf(s, " - ");
|
|
|
if (!ret)
|
|
@@ -421,32 +467,31 @@ static enum print_line_t kmemtrace_print_line(struct trace_iterator *iter)
|
|
|
{
|
|
|
struct trace_entry *entry = iter->ent;
|
|
|
|
|
|
- switch (entry->type) {
|
|
|
- case TRACE_KMEM_ALLOC: {
|
|
|
- struct kmemtrace_alloc_entry *field;
|
|
|
-
|
|
|
- trace_assign_type(field, entry);
|
|
|
- if (kmem_tracer_flags.val & TRACE_KMEM_OPT_MINIMAL)
|
|
|
- return kmemtrace_print_alloc_compress(iter, field);
|
|
|
- else
|
|
|
- return kmemtrace_print_alloc_user(iter, field);
|
|
|
- }
|
|
|
-
|
|
|
- case TRACE_KMEM_FREE: {
|
|
|
- struct kmemtrace_free_entry *field;
|
|
|
-
|
|
|
- trace_assign_type(field, entry);
|
|
|
- if (kmem_tracer_flags.val & TRACE_KMEM_OPT_MINIMAL)
|
|
|
- return kmemtrace_print_free_compress(iter, field);
|
|
|
- else
|
|
|
- return kmemtrace_print_free_user(iter, field);
|
|
|
- }
|
|
|
+ if (!(kmem_tracer_flags.val & TRACE_KMEM_OPT_MINIMAL))
|
|
|
+ return TRACE_TYPE_UNHANDLED;
|
|
|
|
|
|
+ switch (entry->type) {
|
|
|
+ case TRACE_KMEM_ALLOC:
|
|
|
+ return kmemtrace_print_alloc_compress(iter);
|
|
|
+ case TRACE_KMEM_FREE:
|
|
|
+ return kmemtrace_print_free_compress(iter);
|
|
|
default:
|
|
|
return TRACE_TYPE_UNHANDLED;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static struct trace_event kmem_trace_alloc = {
|
|
|
+ .type = TRACE_KMEM_ALLOC,
|
|
|
+ .trace = kmemtrace_print_alloc_user,
|
|
|
+ .binary = kmemtrace_print_alloc_user_bin,
|
|
|
+};
|
|
|
+
|
|
|
+static struct trace_event kmem_trace_free = {
|
|
|
+ .type = TRACE_KMEM_FREE,
|
|
|
+ .trace = kmemtrace_print_free_user,
|
|
|
+ .binary = kmemtrace_print_free_user_bin,
|
|
|
+};
|
|
|
+
|
|
|
static struct tracer kmem_tracer __read_mostly = {
|
|
|
.name = "kmemtrace",
|
|
|
.init = kmem_trace_init,
|
|
@@ -463,6 +508,21 @@ void kmemtrace_init(void)
|
|
|
|
|
|
static int __init init_kmem_tracer(void)
|
|
|
{
|
|
|
- return register_tracer(&kmem_tracer);
|
|
|
+ if (!register_ftrace_event(&kmem_trace_alloc)) {
|
|
|
+ pr_warning("Warning: could not register kmem events\n");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!register_ftrace_event(&kmem_trace_free)) {
|
|
|
+ pr_warning("Warning: could not register kmem events\n");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!register_tracer(&kmem_tracer)) {
|
|
|
+ pr_warning("Warning: could not register the kmem tracer\n");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
device_initcall(init_kmem_tracer);
|