![]() | ||||||||||
Messages in this thread Patch in this message |
Hello, Currently there is no way for modules to define dynamically sized caches that shrink upon memory pressure. We need this for implementing Extended Attribute caches on ext2, ext3, and ReiserFS. Other caches could also make use of the same mechanism (e.g., nfsd's permission cache, dcache, icache, dqache). I propose this patch, which adds the register_cache() and unregister_cache() functions. They allow to register a callback which is invoked on memory pressure. This callback shall then try to free some memory; the parameters and semantics are similar to the other shrink functions in mm/vmscan.c. Regards, Andreas. ------------------------------------------------------------------ Andreas Gruenbacher SuSE Linux AG mailto:agruen@suse.de Deutschherrnstr. 15-19 http://www.suse.de/ D-90429 Nuernberg, GermanyModular 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; } | |||||||||
| Last update: 2005-03-22 12:27 [from the cache] ©2003-2008 | ||||||||||