mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
9811e35359
One BPF program attaches to kmem_cache_alloc_node() and remembers all allocated objects in the map. Another program attaches to kmem_cache_free() and deletes corresponding object from the map. User space walks the map every second and prints any objects which are older than 1 second. Usage: $ sudo tracex4 Then start few long living processes. The 'tracex4' will print something like this: obj 0xffff880465928000 is 13sec old was allocated at ip ffffffff8105dc32 obj 0xffff88043181c280 is 13sec old was allocated at ip ffffffff8105dc32 obj 0xffff880465848000 is 8sec old was allocated at ip ffffffff8105dc32 obj 0xffff8804338bc280 is 15sec old was allocated at ip ffffffff8105dc32 $ addr2line -fispe vmlinux ffffffff8105dc32 do_fork at fork.c:1665 As soon as processes exit the memory is reclaimed and 'tracex4' prints nothing. Similar experiment can be done with the __kmalloc()/kfree() pair. Signed-off-by: Alexei Starovoitov <ast@plumgrid.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnaldo Carvalho de Melo <acme@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: David S. Miller <davem@davemloft.net> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Link: http://lkml.kernel.org/r/1427312966-8434-10-git-send-email-ast@plumgrid.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
69 lines
1.4 KiB
C
69 lines
1.4 KiB
C
/* Copyright (c) 2015 PLUMgrid, http://plumgrid.com
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of version 2 of the GNU General Public
|
|
* License as published by the Free Software Foundation.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <linux/bpf.h>
|
|
#include "libbpf.h"
|
|
#include "bpf_load.h"
|
|
|
|
struct pair {
|
|
long long val;
|
|
__u64 ip;
|
|
};
|
|
|
|
static __u64 time_get_ns(void)
|
|
{
|
|
struct timespec ts;
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
return ts.tv_sec * 1000000000ull + ts.tv_nsec;
|
|
}
|
|
|
|
static void print_old_objects(int fd)
|
|
{
|
|
long long val = time_get_ns();
|
|
__u64 key, next_key;
|
|
struct pair v;
|
|
|
|
key = write(1, "\e[1;1H\e[2J", 12); /* clear screen */
|
|
|
|
key = -1;
|
|
while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
|
|
bpf_lookup_elem(map_fd[0], &next_key, &v);
|
|
key = next_key;
|
|
if (val - v.val < 1000000000ll)
|
|
/* object was allocated more then 1 sec ago */
|
|
continue;
|
|
printf("obj 0x%llx is %2lldsec old was allocated at ip %llx\n",
|
|
next_key, (val - v.val) / 1000000000ll, v.ip);
|
|
}
|
|
}
|
|
|
|
int main(int ac, char **argv)
|
|
{
|
|
char filename[256];
|
|
int i;
|
|
|
|
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
|
|
|
if (load_bpf_file(filename)) {
|
|
printf("%s", bpf_log_buf);
|
|
return 1;
|
|
}
|
|
|
|
for (i = 0; ; i++) {
|
|
print_old_objects(map_fd[1]);
|
|
sleep(1);
|
|
}
|
|
|
|
return 0;
|
|
}
|