diff -Naur linux-2.4.20/Makefile linux-2.4.20-kmemprof/Makefile
--- linux-2.4.20/Makefile	2002-11-29 08:53:16.000000000 +0900
+++ linux-2.4.20-kmemprof/Makefile	2003-06-04 17:12:54.000000000 +0900
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 20
-EXTRAVERSION =
+EXTRAVERSION = -kmemprof
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -Naur linux-2.4.20/include/linux/kmemprof.h linux-2.4.20-kmemprof/include/linux/kmemprof.h
--- linux-2.4.20/include/linux/kmemprof.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.4.20-kmemprof/include/linux/kmemprof.h	2003-06-04 18:02:33.000000000 +0900
@@ -0,0 +1,33 @@
+#ifndef _LINUX_KMEMPROF_H
+#define _LINUX_KMEMPROF_H
+
+enum kmemprof_event_type {
+	KMEM_ALLOC,
+	KMEM_FREE
+};
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/notifier.h>
+#include <linux/slab.h>
+
+
+struct kmemprof_event {
+	enum kmemprof_event_type type;
+	kmem_cache_t * cache;
+	int flags;	/* it is significant in case of type == KMEM_ALLOC */
+	void * obj;
+	void * frame;
+	void * eip;
+};
+
+extern void kmemprof_notifier_call_chain (enum kmemprof_event_type type,
+					struct kmemprof_event * event);
+extern int kmemprof_notifier_chain_register(struct notifier_block * nb);
+extern int kmemprof_notifier_chain_unregister(struct notifier_block * nb);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_KMEMPROF_H */
+
diff -Naur linux-2.4.20/include/linux/slab.h linux-2.4.20-kmemprof/include/linux/slab.h
--- linux-2.4.20/include/linux/slab.h	2002-11-29 08:53:15.000000000 +0900
+++ linux-2.4.20-kmemprof/include/linux/slab.h	2003-06-04 18:33:04.000000000 +0900
@@ -58,6 +58,7 @@
 extern void *kmem_cache_alloc(kmem_cache_t *, int);
 extern void kmem_cache_free(kmem_cache_t *, void *);
 extern unsigned int kmem_cache_size(kmem_cache_t *);
+extern const char * kmem_cache_name(kmem_cache_t *cachep);
 
 extern void *kmalloc(size_t, int);
 extern void kfree(const void *);
diff -Naur linux-2.4.20/kernel/ksyms.c linux-2.4.20-kmemprof/kernel/ksyms.c
--- linux-2.4.20/kernel/ksyms.c	2002-11-29 08:53:15.000000000 +0900
+++ linux-2.4.20-kmemprof/kernel/ksyms.c	2003-06-04 18:32:20.000000000 +0900
@@ -106,6 +106,7 @@
 EXPORT_SYMBOL(kmem_cache_alloc);
 EXPORT_SYMBOL(kmem_cache_free);
 EXPORT_SYMBOL(kmem_cache_size);
+EXPORT_SYMBOL(kmem_cache_name);
 EXPORT_SYMBOL(kmalloc);
 EXPORT_SYMBOL(kfree);
 EXPORT_SYMBOL(vfree);
diff -Naur linux-2.4.20/mm/Makefile linux-2.4.20-kmemprof/mm/Makefile
--- linux-2.4.20/mm/Makefile	2002-08-03 09:39:46.000000000 +0900
+++ linux-2.4.20-kmemprof/mm/Makefile	2003-06-04 18:51:31.000000000 +0900
@@ -9,12 +9,12 @@
 
 O_TARGET := mm.o
 
-export-objs := shmem.o filemap.o memory.o page_alloc.o
+export-objs := shmem.o filemap.o memory.o page_alloc.o kmemprof.o
 
 obj-y	 := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \
 	    vmalloc.o slab.o bootmem.o swap.o vmscan.o page_io.o \
 	    page_alloc.o swap_state.o swapfile.o numa.o oom_kill.o \
-	    shmem.o
+	    shmem.o kmemprof.o
 
 obj-$(CONFIG_HIGHMEM) += highmem.o
 
diff -Naur linux-2.4.20/mm/kmemprof.c linux-2.4.20-kmemprof/mm/kmemprof.c
--- linux-2.4.20/mm/kmemprof.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.4.20-kmemprof/mm/kmemprof.c	2003-06-04 18:01:41.000000000 +0900
@@ -0,0 +1,34 @@
+/*
+ * linux/mm/kmemprof.c
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/kmemprof.h>
+
+static struct notifier_block * kmemprof_notifier;
+
+void kmemprof_notifier_call_chain (enum kmemprof_event_type type,
+					struct kmemprof_event * event)
+{
+	notifier_call_chain (&kmemprof_notifier, type, event);
+}
+
+int kmemprof_notifier_chain_register(struct notifier_block * nb)
+{
+	int err;
+	err = notifier_chain_register (&kmemprof_notifier, nb);
+	return err;
+}
+
+int kmemprof_notifier_chain_unregister(struct notifier_block * nb)
+{
+	int err;
+	err = notifier_chain_unregister (&kmemprof_notifier, nb);
+	return err;
+}
+
+EXPORT_SYMBOL(kmemprof_notifier_call_chain);
+EXPORT_SYMBOL(kmemprof_notifier_chain_register);
+EXPORT_SYMBOL(kmemprof_notifier_chain_unregister);
+
diff -Naur linux-2.4.20/mm/slab.c linux-2.4.20-kmemprof/mm/slab.c
--- linux-2.4.20/mm/slab.c	2002-11-29 08:53:15.000000000 +0900
+++ linux-2.4.20-kmemprof/mm/slab.c	2003-06-04 18:31:03.000000000 +0900
@@ -75,6 +75,7 @@
 #include	<linux/compiler.h>
 #include	<linux/seq_file.h>
 #include	<asm/uaccess.h>
+#include	<linux/kmemprof.h>
 
 /*
  * DEBUG	- 1 for kmem_cache_create() to honour; SLAB_DEBUG_INITIAL,
@@ -1333,7 +1334,28 @@
 }
 #endif
 
-static inline void * __kmem_cache_alloc (kmem_cache_t *cachep, int flags)
+static inline void * wrapped__kmem_cache_alloc (kmem_cache_t *cachep,
+                                                int flags);
+
+static inline void * __kmem_cache_alloc(kmem_cache_t *cachep, int flags)
+{
+	void * ret;
+	struct kmemprof_event event;
+
+	ret = wrapped__kmem_cache_alloc(cachep, flags);
+
+	event.type = KMEM_ALLOC;
+	event.cache = cachep;
+	event.flags = flags;
+	event.obj = ret;
+	event.frame = __builtin_frame_address(0);
+	event.eip = __builtin_return_address(0);
+	kmemprof_notifier_call_chain(KMEM_ALLOC, &event);
+
+	return ret;
+}
+
+static inline void * wrapped__kmem_cache_alloc (kmem_cache_t *cachep, int flags)
 {
 	unsigned long save_flags;
 	void* objp;
@@ -1488,8 +1510,28 @@
  * __kmem_cache_free
  * called with disabled ints
  */
+static inline void wrapped__kmem_cache_free (kmem_cache_t *cachep,
+                                             void* objp);
+
 static inline void __kmem_cache_free (kmem_cache_t *cachep, void* objp)
 {
+	struct kmemprof_event event;
+
+	event.type = KMEM_FREE;
+	event.cache = cachep;
+	event.flags = 0;
+	event.obj = objp;
+	event.frame = __builtin_frame_address(0);
+	event.eip = __builtin_return_address(0);
+	kmemprof_notifier_call_chain(KMEM_FREE, &event);
+
+	wrapped__kmem_cache_free(cachep, objp);
+
+	return;
+}
+
+static inline void wrapped__kmem_cache_free (kmem_cache_t *cachep, void* objp)
+{
 #ifdef CONFIG_SMP
 	cpucache_t *cc = cc_data(cachep);
 
@@ -1615,6 +1657,11 @@
 	return cachep->objsize;
 }
 
+const char * kmem_cache_name(kmem_cache_t *cachep)
+{
+	        return cachep->name;
+}
+
 kmem_cache_t * kmem_find_general_cachep (size_t size, int gfpflags)
 {
 	cache_sizes_t *csizep = cache_sizes;
