relay: add buffer-only functionality, for early kernel tracing
Subsystems (4)
PATCH 1/1 relay: add buffer-only functionality, for early kernel tracing
relay_open() can now handle NULL base_filename, to register a buffer-only channel. Using a new function, relay_late_setup_files(), one can assign files after creating the channel, thus allowing for doing early tracing in the kernel, before VFS is up. This currently works for tracing just after kmem_init_cache() runs, no earlier.
--- Documentation/filesystems/relay.txt | 11 ++++ include/linux/relay.h | 5 ++ kernel/relay.c | 113 ++++++++++++++++++++++++++--------- 3 files changed, 101 insertions(+), 28 deletions(-)
Documentation/filesystems/relay.txt +11 -0
@@ -161,6 +161,7 @@ TBD(curr. line MT:/API/) relay_close(chan) relay_flush(chan) relay_reset(chan) + relay_late_setup_files(chan, base_filename, parent) channel management typically called on instigation of userspace:
@@ -294,6 +295,16 @@ user-defined data with a channel, and is immediately available (including in create_buf_file()) via chan->private_data or buf->chan->private_data. +Buffer-only channels +-------------------- + +These channels have no files associated and can be created with +relay_open(NULL, NULL, ...). Such channels are useful in scenarios such +as when doing early tracing in the kernel, before the VFS is up. In these +cases, one may open a buffer-only channel and then call +relay_late_setup_files() when the kernel is ready to handle files, +to expose the buffered data to the userspace. + Channel 'modes' ---------------
include/linux/relay.h +5 -0
@@ -48,6 +48,7 @@ struct rchan_bufsize_t *padding;/* padding counts per sub-buffer */ size_t prev_padding;/* temporary variable */ size_t bytes_consumed;/* bytes consumed in cur read subbuf */ +size_t early_bytes;/* bytes consumed before VFS inited */ unsigned int cpu;/* this buf's cpu */ }____cacheline_aligned ;
@@ -68,6 +69,7 @@ struct rchanint is_global;/* One global buffer ? */ struct list_head list;/* for channel list */ struct dentry *parent;/* parent dentry passed to open */ +int has_base_filename;/* has a filename associated? */ char base_filename[NAME_MAX ];/* saved base filename */ };
@@ -169,6 +171,9 @@ struct rchan *relay_open(const char *base_filename,size_t n_subbufs, struct rchan_callbacks *cb, void *private_data); +extern int relay_late_setup_files (struct rchan *chan, +const char *base_filename, +struct dentry *parent);extern void relay_close (struct rchan *chan);extern void relay_flush (struct rchan *chan); extern void relay_subbufs_consumed(struct rchan *chan,
kernel/relay.c +85 -28
184 lines not on this page · raw message
Signature · 1 line
1.5.2.5
This is _not_ a patched intended for merging!
Mathieu, please take a look (maybe test) and see if I didn't mess up the CPU hotplug stuff. AFAICS, it shoudn't be affected, but better be sure.
I have also attached some sample code using this functionality. It currently logs some text on every kmalloc() (SLUB-only), so one can easily check for data corruption. Make sure you enable CONFIG_SLUB and CONFIG_KMEMTRACE.
Oh, and I've tried Tom Zanussi's other e-mail address and Comcast rejects my mails. :(
---
include/linux/kmemtrace.h new file +42 -0
@@ -0,0 +1,42 @@ +/* +* Copyright (C) 2008 Eduard-Gabriel Munteanu +* +* This file is released under GPL version 2. +*/ + +#ifndef _LINUX_KMEMTRACE_H +#define _LINUX_KMEMTRACE_H + +#include <linux/cache.h> +#include <linux/types.h> + +#ifdef __KERNEL__ + +extern int kmemtrace_is_inited__read_mostly ; + +extern void kmemtrace_init (void ); +extern void kmemtrace_track_alloc (void *call_site,const void *ptr, +unsigned long nr_req, +unsigned long nr_alloc, +gfp_t flags); +extern void kmemtrace_track_free (void *call_site,const void *ptr); +extern void kmemtrace_log_string (char *str); + +#endif /* __KERNEL__ */ + +enum kmemtrace_event_id { +KMEM_ALLOC =0x01 , +KMEM_FREE =0x02 , +}; + +struct kmemtrace_event { +enum kmemtrace_event_id event_id; +uintptr_t call_site; +uintptr_t ptr; +unsigned long nr_req; +unsigned long nr_alloc; +unsigned long gfp_flags; +}; + +#endif /* _LINUX_KMEMTRACE_H */ +
include/linux/slub_def.h +29 -9
@@ -11,6 +11,10 @@#include <linux/workqueue.h> #include <linux/kobject.h> +#ifdef CONFIG_KMEMTRACE +#include <linux/kmemtrace.h> +#endif +enum stat_item {ALLOC_FASTPATH ,/* Allocation from cpu slab */ ALLOC_SLOWPATH ,/* Allocation by getting a new cpu slab */
@@ -196,20 +200,36 @@ static __always_inline void *kmalloc_large(size_t size, gfp_t flags) static __always_inline void *kmalloc(size_t size, gfp_t flags) { -if (__builtin_constant_p (size)) { -if (size >PAGE_SIZE ) -return kmalloc_large (size, flags); +void *ret =NULL ; +size_t nr_alloc =0 ; -if (!(flags &SLUB_DMA )) { +if (__builtin_constant_p (size)) { +if (size >PAGE_SIZE ) { + ret =kmalloc_large (size, flags); + nr_alloc =PAGE_SIZE <<get_order (size); + }else if (!(flags &SLUB_DMA )) {struct kmem_cache *s =kmalloc_slab (size); -if (!s) -return ZERO_SIZE_PTR ; - -return kmem_cache_alloc (s, flags); +if (!s) { + ret =ZERO_SIZE_PTR ; + nr_alloc =0 ; + }else { + ret =kmem_cache_alloc (s, flags); + nr_alloc = s->size; + } } + }else { + ret =__kmalloc (size, flags); + nr_alloc = size; } -return __kmalloc (size, flags); + +#ifdef CONFIG_KMEMTRACE +if (kmemtrace_is_inited)/* Has kmemtrace been initialized yet? */ +kmemtrace_track_alloc (__builtin_return_address (0 ), ret, + size, nr_alloc, flags); +#endif + +return ret; }#ifdef CONFIG_NUMA
init/main.c +8 -0
@@ -65,6 +65,10 @@#include <asm/sections.h> #include <asm/cacheflush.h> +#ifdef CONFIG_KMEMTRACE +#include <linux/kmemtrace.h> +#endif +#ifdef CONFIG_X86_LOCAL_APIC #include <asm/smp.h> #endif
@@ -610,6 +614,10 @@ asmlinkage void __init start_kernel(void)enable_debug_pagealloc ();cpu_hotplug_init ();kmem_cache_init (); +#ifdef CONFIG_KMEMTRACE +kmemtrace_init (); +kmemtrace_log_string ("kmemtrace_init() just ran!\n" ); +#endif setup_per_cpu_pageset ();numa_policy_init ();if (late_time_init)
mm/Kconfig +5 -0
@@ -1,3 +1,8 @@ +config KMEMTRACE + bool "Kernel memory tracer" + depends on SLUB + default n + config SELECT_MEMORY_MODEL def_bool y depends on EXPERIMENTAL || ARCH_SELECT_MEMORY_MODEL
mm/Makefile +1 -0
@@ -33,4 +33,5 @@ obj-$(CONFIG_MIGRATION) += migrate.o obj-$(CONFIG_SMP) += allocpercpu.o obj-$(CONFIG_QUICKLIST) += quicklist.o obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o +obj-$(CONFIG_KMEMTRACE) += kmemtrace.o
mm/kmemtrace.c new file +116 -0
116 lines not on this page · raw message