All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro>
To: Mathieu Desnoyers <compudj@krystal.dyndns.org>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>,
	LKML <linux-kernel@vger.kernel.org>,
	Randy Dunlap <randy.dunlap@oracle.com>,
	Tom Zanussi <zanussi@comcast.net>
Subject: Re: [PATCH] relay: add buffer-only functionality, for early kernel tracing
Date: Sun, 6 Apr 2008 20:48:53 +0300	[thread overview]
Message-ID: <20080406204853.66a6f263@linux360.ro> (raw)
In-Reply-To: <20080406203426.40431e74@linux360.ro>


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. :(

---
diff --git a/include/linux/kmemtrace.h b/include/linux/kmemtrace.h
new file mode 100644
index 0000000..8b7eda9
--- /dev/null
+++ b/include/linux/kmemtrace.h
@@ -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 */
+
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index b00c1c7..53e62f7 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -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
diff --git a/init/main.c b/init/main.c
index 99ce949..26db1c1 100644
--- a/init/main.c
+++ b/init/main.c
@@ -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)
diff --git a/mm/Kconfig b/mm/Kconfig
index 0016ebd..b12555b 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -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
diff --git a/mm/Makefile b/mm/Makefile
index a5b0dd9..67aa3f4 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -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
 
diff --git a/mm/kmemtrace.c b/mm/kmemtrace.c
new file mode 100644
index 0000000..4ecefc4
--- /dev/null
+++ b/mm/kmemtrace.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2008 Pekka Enberg, Eduard-Gabriel Munteanu
+ *
+ * This file is released under GPL version 2.
+ */
+
+#include <linux/kmemtrace.h>
+#include <linux/string.h>
+#include <linux/debugfs.h>
+#include <linux/relay.h>
+#include <linux/module.h>
+
+#define KMEMTRACE_SUBBUF_SIZE	262144
+#define KMEMTRACE_NR_SUBBUFS	4
+
+static struct rchan *kmemtrace_chan;
+
+static inline void kmemtrace_log_event(struct kmemtrace_event *event)
+{
+	relay_write(kmemtrace_chan, event, sizeof(struct kmemtrace_event));
+}
+
+void kmemtrace_log_string(char *str)
+{
+	relay_write(kmemtrace_chan, str, strlen(str) + 1);
+}
+
+void kmemtrace_track_alloc(void *call_site, const void *ptr,
+			   unsigned long nr_req, unsigned long nr_alloc,
+			   gfp_t flags)
+{
+	struct kmemtrace_event ev = {
+		.event_id	= KMEM_ALLOC,
+		.call_site	= (uintptr_t) call_site,
+		.ptr		= (uintptr_t) ptr,
+		.nr_req		= nr_req,
+		.nr_alloc	= nr_alloc,
+		.gfp_flags	= flags,
+	};
+
+	/*kmemtrace_log_event(&ev);*/
+	kmemtrace_log_string("ABCDEFGHIJKLMNOPQRSTUVWXYZa");
+}
+EXPORT_SYMBOL(kmemtrace_track_alloc);
+
+void kmemtrace_track_free(void *call_site, const void *ptr)
+{
+	struct kmemtrace_event ev = {
+		.event_id	= KMEM_FREE,
+		.call_site	= (uintptr_t) call_site,
+		.ptr		= (uintptr_t) ptr,
+	};
+
+	kmemtrace_log_event(&ev);
+}
+EXPORT_SYMBOL(kmemtrace_track_free);
+
+
+static struct dentry
+*kmemtrace_create_buf_file(const char *filename, struct dentry *parent,
+			   int mode, struct rchan_buf *buf, int *is_global)
+{
+	return debugfs_create_file(filename, mode, parent, buf,
+				   &relay_file_operations);
+}
+
+static int kmemtrace_remove_buf_file(struct dentry *dentry)
+{
+	debugfs_remove(dentry);
+
+	return 0;
+}
+
+static struct rchan_callbacks relay_callbacks = {
+	.create_buf_file = kmemtrace_create_buf_file,
+	.remove_buf_file = kmemtrace_remove_buf_file,
+};
+
+static struct dentry *kmemtrace_dir;
+
+static int __init kmemtrace_setup_late(void)
+{
+	if (!kmemtrace_chan)
+		goto failed;
+	
+	kmemtrace_dir = debugfs_create_dir("kmemtrace", NULL);
+	if (!kmemtrace_dir)
+		goto failed;
+
+	relay_late_setup_files(kmemtrace_chan, "cpu", kmemtrace_dir);
+
+	kmemtrace_log_string("Late setup ran!\n");
+
+	return 0;
+
+failed:
+	return 1;
+}
+late_initcall(kmemtrace_setup_late);
+
+int kmemtrace_is_inited __read_mostly = 0;
+EXPORT_SYMBOL(kmemtrace_is_inited);
+
+void kmemtrace_init(void)
+{
+	kmemtrace_chan = relay_open(NULL, NULL, KMEMTRACE_SUBBUF_SIZE,
+				    KMEMTRACE_NR_SUBBUFS, &relay_callbacks, 
+				    NULL);
+	if (!kmemtrace_chan) {
+		printk("kmemtrace: could not open relay channel\n");
+		return;
+	}
+
+	kmemtrace_is_inited = 1;
+}
+

      reply	other threads:[~2008-04-06 17:49 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-06 17:34 [PATCH] relay: add buffer-only functionality, for early kernel tracing Eduard - Gabriel Munteanu
2008-04-06 17:48 ` Eduard - Gabriel Munteanu [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080406204853.66a6f263@linux360.ro \
    --to=eduard.munteanu@linux360.ro \
    --cc=compudj@krystal.dyndns.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=penberg@cs.helsinki.fi \
    --cc=randy.dunlap@oracle.com \
    --cc=zanussi@comcast.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.