Modular caches that shrink automatically

This patch adds the register_cache() and unregister_cache() functions which
register a callback that is invoked on memory pressure to free some memory. The
parameters and semantics to the callback are similar to the other shrink
functions.

diff -Nur linux-2.5.30/include/linux/cache_def.h linux-2.5.30.patch/include/linux/cache_def.h
--- linux-2.5.30/include/linux/cache_def.h	Thu Jan  1 01:00:00 1970
+++ linux-2.5.30.patch/include/linux/cache_def.h	Sat Aug  3 13:58:07 2002
@@ -0,0 +1,15 @@
+/*
+ * linux/cache_def.h
+ * Modular caches that shrink automatically
+ *
+ * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ */
+
+struct cache_definition {
+	const char *name;
+	void (*shrink)(int, unsigned int);
+	struct list_head link;
+};
+
+extern void register_cache(struct cache_definition *);
+extern void unregister_cache(struct cache_definition *);
diff -Nur linux-2.5.30/kernel/ksyms.c linux-2.5.30.patch/kernel/ksyms.c
--- linux-2.5.30/kernel/ksyms.c	Thu Aug  1 23:16:02 2002
+++ linux-2.5.30.patch/kernel/ksyms.c	Fri Aug  2 15:57:42 2002
@@ -31,6 +31,7 @@
 #include <linux/genhd.h>
 #include <linux/blkpg.h>
 #include <linux/swap.h>
+#include <linux/cache_def.h>
 #include <linux/ctype.h>
 #include <linux/file.h>
 #include <linux/iobuf.h>
@@ -106,6 +107,8 @@
 EXPORT_SYMBOL(kmem_cache_alloc);
 EXPORT_SYMBOL(kmem_cache_free);
 EXPORT_SYMBOL(kmem_cache_size);
+EXPORT_SYMBOL(register_cache);
+EXPORT_SYMBOL(unregister_cache);
 EXPORT_SYMBOL(kmalloc);
 EXPORT_SYMBOL(kfree);
 EXPORT_SYMBOL(vfree);
Binary files linux-2.5.30/mm/.vmscan.c.swp and linux-2.5.30.patch/mm/.vmscan.c.swp differ
diff -Nur linux-2.5.30/mm/vmscan.c linux-2.5.30.patch/mm/vmscan.c
--- linux-2.5.30/mm/vmscan.c	Thu Aug  1 23:16:08 2002
+++ linux-2.5.30.patch/mm/vmscan.c	Sat Aug  3 13:56:55 2002
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/kernel_stat.h>
 #include <linux/swap.h>
+#include <linux/cache_def.h>
 #include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
@@ -61,6 +62,39 @@
 	return 0;
 }
 
+static DECLARE_MUTEX(other_caches_lock);
+static LIST_HEAD(other_caches);
+
+void register_cache(struct cache_definition *cache)
+{
+	down(&other_caches_lock);
+	list_add(&cache->link, &other_caches);
+	up(&other_caches_lock);
+}
+
+void unregister_cache(struct cache_definition *cache)
+{
+	down(&other_caches_lock);
+	list_del(&cache->link);
+	up(&other_caches_lock);
+}
+
+static void shrink_other_caches(unsigned int priority, int gfp_mask)
+{
+	struct list_head *p = other_caches.prev;
+
+	down(&other_caches_lock);
+	while (p != &other_caches) {
+		struct cache_definition *cache =
+			list_entry(p, struct cache_definition, link);
+
+		cache->shrink(priority, gfp_mask);
+		p = p->prev;
+	}
+	up(&other_caches_lock);
+}
+
+
 static int
 shrink_cache(int nr_pages, zone_t *classzone,
 		unsigned int gfp_mask, int priority, int max_scan)
@@ -395,6 +429,7 @@
 #ifdef CONFIG_QUOTA
 	shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
 #endif
+	shrink_other_caches(priority, gfp_mask);
 
 	return nr_pages;
 }

