2009-07-03 09:33:39

by Li Zefan

[permalink] [raw]
Subject: [PATCH v2] kmemtrace: print binary output only if 'bin' option is set

Currently by default the output of kmemtrace is binary format instead
of human-readable output.

This patch makes the following changes:
- We'll see human-readable output by default
- We'll see binary output if 'bin' option is set

Note: you may probably need to explicitly disable context-info binary
output:

# echo 0 > options/context-info
# echo 1 > options/bin
# cat trace_pipe

v2:
- use %pF to print call_site

Signed-off-by: Li Zefan <[email protected]>
Acked-by: Pekka Enberg <[email protected]>
Acked-by: Eduard - Gabriel Munteanu <[email protected]>
---
kernel/trace/kmemtrace.c | 120 ++++++++++++++++++++++++++++++++++-----------
1 files changed, 90 insertions(+), 30 deletions(-)

diff --git a/kernel/trace/kmemtrace.c b/kernel/trace/kmemtrace.c
index 1edaa95..74903b6 100644
--- a/kernel/trace/kmemtrace.c
+++ b/kernel/trace/kmemtrace.c
@@ -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);
--
1.5.4.rc3


2009-07-03 09:43:28

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH v2] kmemtrace: print binary output only if 'bin' option is set


* Li Zefan <[email protected]> wrote:

> Currently by default the output of kmemtrace is binary format
> instead of human-readable output.
>
> This patch makes the following changes:
> - We'll see human-readable output by default
> - We'll see binary output if 'bin' option is set
>
> Note: you may probably need to explicitly disable context-info binary
> output:
>
> # echo 0 > options/context-info
> # echo 1 > options/bin
> # cat trace_pipe
>
> v2:
> - use %pF to print call_site
>
> Signed-off-by: Li Zefan <[email protected]>
> Acked-by: Pekka Enberg <[email protected]>
> Acked-by: Eduard - Gabriel Munteanu <[email protected]>
> ---
> kernel/trace/kmemtrace.c | 120 ++++++++++++++++++++++++++++++++++-----------
> 1 files changed, 90 insertions(+), 30 deletions(-)

Applied to tip:tracing/core (for .32), thanks guys!

Btw., any progress on turning kmemtrace into a 'perf kmemtrace' kind
of tool? It would be really cool: mixing it with PMU events would
enhance it to a large degree and there's various good output modes
implemented in tools/perf/ that would make analysis rather
expressive and flexible.

For that we'd have to extend PERF_TYPE_TRACEPOINT to do samples as
well. See kernel/perf_counter.c, include/linux/perf_counter.h, etc.

For example, using call-graphs one can get output like the one
attached below. (it shows the SLAB profile details from a hackbench
run, a graph form.)

Ingo

#
# (39812 samples)
#
# Overhead Symbol
# ........ ......
#
23.58% [k] _spin_lock
|
|--9.77%-- get_partial_node
| |
| |--8.76%-- __slab_alloc
| | |
| | |--5.22%-- kmem_cache_alloc_node
| | | __alloc_skb
| | | sock_alloc_send_pskb
| | | __sk_free
| | | unix_stream_sendmsg
| | | __sock_recvmsg
| | | sock_aio_read
| | | do_sync_write
| | | vfs_write
| | | sys_write
| | | sysenter_dispatch
| | | 0xf7f07430
| | | 0xffe8255000000014
| | |
| | --3.54%-- __kmalloc_node_track_caller
| | __alloc_skb
| | sock_alloc_send_pskb
| | __sk_free
| | unix_stream_sendmsg
| | __sock_recvmsg
| | sock_aio_read
| | do_sync_write
| | vfs_write
| | sys_write
| | sysenter_dispatch
| | 0xf7f07430
| | 0xffe8255000000014
| |
| --1.00%-- get_any_partial
| __slab_alloc
| |
| |--0.56%-- kmem_cache_alloc_node
| | __alloc_skb
| | sock_alloc_send_pskb
| | __sk_free
| | unix_stream_sendmsg
| | __sock_recvmsg
| | sock_aio_read
| | do_sync_write
| | vfs_write
| | sys_write
| | sysenter_dispatch
| | 0xf7f07430
| | 0xffe8255000000014
| |
| --0.44%-- __kmalloc_node_track_caller
| __alloc_skb
| sock_alloc_send_pskb
| __sk_free
| unix_stream_sendmsg
| __sock_recvmsg
| sock_aio_read
| do_sync_write
| vfs_write
| sys_write
| sysenter_dispatch
| 0xf7f07430
| 0xffe8255000000014
|
|--9.51%-- add_partial
| __slab_free
| |
| |--5.60%-- kmem_cache_free
| | |
| | |--5.60%-- skb_tstamp_tx
| | | skb_tstamp_tx
| | | unix_stream_recvmsg
| | | sock_aio_read
| | | sys_getsockopt
| | | do_sync_read
| | | vfs_read
| | | sys_read
| | | sysenter_dispatch
| | | 0xf7f07430
| | | 0x9000007d0
| | |
| | --0.00%-- __d_free
| | d_free
| | d_kill
| | dput
| | __fput
| | fput
| | filp_close
| | put_files_struct
| | exit_files
| | do_exit
| | do_group_exit
| | sys_exit_group
| | sysenter_dispatch
| |
| --3.91%-- kfree
| |
| |--3.91%-- pskb_expand_head
| | __pskb_pull_tail
| | kfree_skb
| | skb_tstamp_tx
| | unix_stream_recvmsg
| | sock_aio_read
| | sys_getsockopt
| | do_sync_read
| | vfs_read
| | sys_read
| | sysenter_dispatch
| | 0xf7f07430
| | 0x9000007d0
| |
| --0.00%-- free_counter_rcu
| __rcu_process_callbacks
| rcu_process_callbacks
| __do_softirq
| call_softirq
| do_softirq
| irq_exit
| smp_apic_timer_interrupt
| apic_timer_interrupt
| 0xf7f07430
| 0x9000007d0
|
|--2.04%-- unix_stream_sendmsg
| __sock_recvmsg
| sock_aio_read
| do_sync_write
| vfs_write
| sys_write
| sysenter_dispatch
| 0xf7f07430
| |
| |--2.03%-- 0xffe8255000000014
| |
| --0.01%-- 0x700000006
|
|--1.26%-- task_rq_lock
| try_to_wake_up
| default_wake_function
| |
| |--1.26%-- autoremove_wake_function
| | __wake_up_common
| | __wake_up_sync_key
| | |
[...]

2009-07-03 09:55:59

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH v2] kmemtrace: print binary output only if 'bin' option is set


* Eduard - Gabriel Munteanu <[email protected]> wrote:

> On Fri, Jul 03, 2009 at 05:34:24PM +0800, Li Zefan wrote:
> > Currently by default the output of kmemtrace is binary format instead
> > of human-readable output.
> >
> > This patch makes the following changes:
> > - We'll see human-readable output by default
> > - We'll see binary output if 'bin' option is set
> >
> > Note: you may probably need to explicitly disable context-info binary
> > output:
> >
> > # echo 0 > options/context-info
> > # echo 1 > options/bin
> > # cat trace_pipe
> >
> > v2:
> > - use %pF to print call_site
> >
> > Signed-off-by: Li Zefan <[email protected]>
> > Acked-by: Pekka Enberg <[email protected]>
> > Acked-by: Eduard - Gabriel Munteanu <[email protected]>
> > ---
> > kernel/trace/kmemtrace.c | 120 ++++++++++++++++++++++++++++++++++-----------
> > 1 files changed, 90 insertions(+), 30 deletions(-)
> >
> > diff --git a/kernel/trace/kmemtrace.c b/kernel/trace/kmemtrace.c
> > index 1edaa95..74903b6 100644
> > --- a/kernel/trace/kmemtrace.c
> > +++ b/kernel/trace/kmemtrace.c
> > @@ -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;
> > +}
>
> [snip]
>
> kmemtrace_print_alloc_user() is meant for kmemtrace-user, that's
> what the naming is meant to convey. Also,
> kmemtrace_print_alloc_user_bin is kinda long. Could you leave the
> former as it was and come up with another name for the non-binary
> variant?

should i hold off on this patch for now?

Ingo

Subject: Re: [PATCH v2] kmemtrace: print binary output only if 'bin' option is set

On Fri, Jul 03, 2009 at 05:34:24PM +0800, Li Zefan wrote:
> Currently by default the output of kmemtrace is binary format instead
> of human-readable output.
>
> This patch makes the following changes:
> - We'll see human-readable output by default
> - We'll see binary output if 'bin' option is set
>
> Note: you may probably need to explicitly disable context-info binary
> output:
>
> # echo 0 > options/context-info
> # echo 1 > options/bin
> # cat trace_pipe
>
> v2:
> - use %pF to print call_site
>
> Signed-off-by: Li Zefan <[email protected]>
> Acked-by: Pekka Enberg <[email protected]>
> Acked-by: Eduard - Gabriel Munteanu <[email protected]>
> ---
> kernel/trace/kmemtrace.c | 120 ++++++++++++++++++++++++++++++++++-----------
> 1 files changed, 90 insertions(+), 30 deletions(-)
>
> diff --git a/kernel/trace/kmemtrace.c b/kernel/trace/kmemtrace.c
> index 1edaa95..74903b6 100644
> --- a/kernel/trace/kmemtrace.c
> +++ b/kernel/trace/kmemtrace.c
> @@ -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;
> +}

[snip]

kmemtrace_print_alloc_user() is meant for kmemtrace-user, that's what the
naming is meant to convey. Also, kmemtrace_print_alloc_user_bin is kinda
long. Could you leave the former as it was and come up with another name
for the non-binary variant?


Eduard

2009-07-03 10:22:37

by Li Zefan

[permalink] [raw]
Subject: [tip:tracing/core] kmemtrace: Print binary output only if 'bin' option is set

Commit-ID: ddc1637af217dbd8bc51f30e6d24e84476a869a6
Gitweb: http://git.kernel.org/tip/ddc1637af217dbd8bc51f30e6d24e84476a869a6
Author: Li Zefan <[email protected]>
AuthorDate: Fri, 3 Jul 2009 17:34:24 +0800
Committer: Ingo Molnar <[email protected]>
CommitDate: Fri, 3 Jul 2009 11:39:46 +0200

kmemtrace: Print binary output only if 'bin' option is set

Currently by default the output of kmemtrace is binary format instead
of human-readable output.

This patch makes the following changes:

- We'll see human-readable output by default
- We'll see binary output if 'bin' option is set

Note: you may probably need to explicitly disable context-info binary
output:

# echo 0 > options/context-info
# echo 1 > options/bin
# cat trace_pipe

v2:
- use %pF to print call_site

Signed-off-by: Li Zefan <[email protected]>
Acked-by: Pekka Enberg <[email protected]>
Acked-by: Eduard - Gabriel Munteanu <[email protected]>
Cc: Steven Rostedt <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>


---
kernel/trace/kmemtrace.c | 120 ++++++++++++++++++++++++++++++++++-----------
1 files changed, 90 insertions(+), 30 deletions(-)

diff --git a/kernel/trace/kmemtrace.c b/kernel/trace/kmemtrace.c
index 1edaa95..74903b6 100644
--- a/kernel/trace/kmemtrace.c
+++ b/kernel/trace/kmemtrace.c
@@ -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);