linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Ed Tomlinson <tomlins@cam.org>
To: linux-mm@kvack.org
Cc: Andrew Morton <akpm@digeo.com>
Subject: [PATCH] ageable slab callbacks
Date: Sun, 15 Sep 2002 14:36:20 -0400	[thread overview]
Message-ID: <200209151436.20171.tomlins@cam.org> (raw)

Hi,

This lets the vm use callbacks to shrink ageable caches.   With this we avoid
having to change vmscan if an ageable cache family is added.  It also batches
calls to the prune methods (SHRINK_BATCH).

patch is against 34-mm1, which is the latest I can test with here (ide problems). 

I have set the DEFAULT_SEEKS to 2.  Lets see if the extra pressure helps.

Comments
Ed Tomlinson

---------- slab_callbacks_A0
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.627   -> 1.628  
#	         fs/dcache.c	1.30    -> 1.31   
#	         mm/vmscan.c	1.102   -> 1.103  
#	include/linux/slab.h	1.12    -> 1.13   
#	          fs/dquot.c	1.45    -> 1.46   
#	           mm/slab.c	1.27    -> 1.28   
#	          fs/inode.c	1.68    -> 1.69   
#	include/linux/dcache.h	1.16    -> 1.17   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/09/15	ed@oscar.et.ca	1.628
# Introduce callbacks to shrink ageable caches.  With this we do not
# have to change vmscan when we add a new cache family with its own 
# ageing method.  Note that these are not necessarily per cache.  For
# example there is one aging method used for all inode caches.
# --------------------------------------------
#
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c	Sun Sep 15 14:28:45 2002
+++ b/fs/dcache.c	Sun Sep 15 14:28:45 2002
@@ -570,9 +570,9 @@
  * This is called from kswapd when we think we need some
  * more memory. 
  */
-int shrink_dcache_memory(int ratio, unsigned int gfp_mask)
+int shrink_dcache_memory(int nr, int ratio, unsigned int gfp_mask)
 {
-	int entries = dentry_stat.nr_dentry / ratio + 1;
+	nr += dentry_stat.nr_dentry / ratio + 1;
 	/*
 	 * Nasty deadlock avoidance.
 	 *
@@ -584,11 +584,11 @@
 	 * We should make sure we don't hold the superblock lock over
 	 * block allocations, but for now:
 	 */
-	if (!(gfp_mask & __GFP_FS))
-		return 0;
+	if (!(gfp_mask & __GFP_FS) | (nr < SHRINK_BATCH))
+		return nr;
 
-	prune_dcache(entries);
-	return entries;
+	prune_dcache(nr);
+	return 0;
 }
 
 #define NAME_ALLOC_LEN(len)	((len+16) & ~15)
@@ -1328,6 +1328,8 @@
 					 NULL, NULL);
 	if (!dentry_cache)
 		panic("Cannot create dentry cache");
+	
+	kmem_set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory);
 
 #if PAGE_SHIFT < 13
 	mempages >>= (13 - PAGE_SHIFT);
@@ -1401,6 +1403,8 @@
 			SLAB_HWCACHE_ALIGN, NULL, NULL);
 	if (!dquot_cachep)
 		panic("Cannot create dquot SLAB cache");
+
+	kmem_set_shrinker(DEFAULT_SEEKS, shrink_dquot_memory);
 #endif
 
 	dcache_init(mempages);
diff -Nru a/fs/dquot.c b/fs/dquot.c
--- a/fs/dquot.c	Sun Sep 15 14:28:45 2002
+++ b/fs/dquot.c	Sun Sep 15 14:28:45 2002
@@ -483,14 +483,17 @@
  * more memory
  */
 
-int shrink_dqcache_memory(int ratio, unsigned int gfp_mask)
+int shrink_dqcache_memory(int nr, int ratio, unsigned int gfp_mask)
 {
-	int entries = dqstats.allocated_dquots / ratio + 1;
+	nr += dqstats.allocated_dquots / ratio + 1;
+
+	if (nr < SHRINK_BATCH)
+		return nr; 
 
 	lock_kernel();
-	prune_dqcache(entries);
+	prune_dqcache(nr);
 	unlock_kernel();
-	return entries;
+	return 0;
 }
 
 /*
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	Sun Sep 15 14:28:45 2002
+++ b/fs/inode.c	Sun Sep 15 14:28:45 2002
@@ -417,9 +417,9 @@
  * This is called from kswapd when we think we need some
  * more memory. 
  */
-int shrink_icache_memory(int ratio, unsigned int gfp_mask)
+int shrink_icache_memory(int nr, int ratio, unsigned int gfp_mask)
 {
-	int entries = inodes_stat.nr_inodes / ratio + 1;
+	nr += inodes_stat.nr_inodes / ratio + 1;
 	/*
 	 * Nasty deadlock avoidance..
 	 *
@@ -427,11 +427,11 @@
 	 * want to recurse into the FS that called us
 	 * in clear_inode() and friends..
 	 */
-	if (!(gfp_mask & __GFP_FS))
-		return 0;
+	if (!(gfp_mask & __GFP_FS) | (nr < SHRINK_BATCH) )
+		return nr;
 
-	prune_icache(entries);
-	return entries;
+	prune_icache(nr);
+	return 0;
 }
 EXPORT_SYMBOL(shrink_icache_memory);
 
@@ -1096,4 +1096,6 @@
 					 NULL);
 	if (!inode_cachep)
 		panic("cannot create inode slab cache");
+
+	kmem_set_shrinker(DEFAULT_SEEKS, shrink_icache_memory);
 }
diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h
--- a/include/linux/dcache.h	Sun Sep 15 14:28:45 2002
+++ b/include/linux/dcache.h	Sun Sep 15 14:28:45 2002
@@ -182,15 +182,15 @@
 extern int d_invalidate(struct dentry *);
 
 /* dcache memory management */
-extern int shrink_dcache_memory(int, unsigned int);
+extern int shrink_dcache_memory(int, int, unsigned int);
 extern void prune_dcache(int);
 
 /* icache memory management (defined in linux/fs/inode.c) */
-extern int shrink_icache_memory(int, unsigned int);
+extern int shrink_icache_memory(int, int, unsigned int);
 extern void prune_icache(int);
 
 /* quota cache memory management (defined in linux/fs/dquot.c) */
-extern int shrink_dqcache_memory(int, unsigned int);
+extern int shrink_dqcache_memory(int, int, unsigned int);
 
 /* only used at mount-time */
 extern struct dentry * d_alloc_root(struct inode *);
diff -Nru a/include/linux/slab.h b/include/linux/slab.h
--- a/include/linux/slab.h	Sun Sep 15 14:28:45 2002
+++ b/include/linux/slab.h	Sun Sep 15 14:28:45 2002
@@ -45,6 +45,8 @@
 #define SLAB_CTOR_ATOMIC	0x002UL		/* tell constructor it can't sleep */
 #define	SLAB_CTOR_VERIFY	0x004UL		/* tell constructor it's a verify call */
 
+typedef int (*kmem_shrinker_t)(int, int, unsigned int);
+
 /* prototypes */
 extern void kmem_cache_init(void);
 extern void kmem_cache_sizes_init(void);
@@ -61,6 +63,12 @@
 
 extern void *kmalloc(size_t, int);
 extern void kfree(const void *);
+
+#define SHRINK_BATCH 32
+#define DEFAULT_SEEKS 2
+
+extern void kmem_set_shrinker(int, kmem_shrinker_t);
+extern int kmem_do_shrinks(int, int, unsigned int);
 
 extern int FASTCALL(kmem_cache_reap(int));
 
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	Sun Sep 15 14:28:45 2002
+++ b/mm/slab.c	Sun Sep 15 14:28:45 2002
@@ -147,6 +147,23 @@
  * Needed to avoid a possible looping condition in kmem_cache_grow().
  */
 static unsigned long offslab_limit;
+ 
+/*
+ * shrinker_t
+ *
+ * Manages list of shrinker callbacks used by the vm to apply pressure to 
+ * prunable caches.
+ */
+
+typedef struct shrinker_s {
+	kmem_shrinker_t		shrinker;
+	struct list_head	next;
+	int 			seeks;	/* seeks to recreate an obj */
+	int			nr;	/* objs pending delete */ 
+} shrinker_t;
+		
+static	spinlock_t		shrinker_lock = SPIN_LOCK_UNLOCKED;
+static	struct list_head	shrinker_list;
 
 /*
  * slab_t
@@ -413,6 +430,42 @@
 static void enable_all_cpucaches (void);
 #endif
 
+/*
+ * Add a shrinker to be called from the vm
+ */
+void kmem_set_shrinker(int seeks, kmem_shrinker_t theshrinker)
+{
+	shrinker_t *shrinkerp;	
+	shrinkerp = kmalloc(sizeof(shrinker_t),GFP_KERNEL);	
+	BUG_ON(!shrinkerp);
+	shrinkerp->shrinker = theshrinker;
+	shrinkerp->seeks = seeks;
+	shrinkerp->nr = 0;
+	spin_lock(&shrinker_lock);
+	list_add(&shrinkerp->next, &shrinker_list);
+	spin_lock(&shrinker_lock);
+}
+
+/* Call the shrink functions to age shrinkable caches */
+int kmem_do_shrinks(int pages, int scanned,  unsigned int gfp_mask)
+{
+struct list_head *p;
+	int ratio;
+
+	spin_lock(&shrinker_lock);
+
+	list_for_each(p,&shrinker_list) {
+		shrinker_t *shrinkerp = list_entry(p, shrinker_t, next);
+		ratio = pages / (shrinkerp->seeks * scanned + 1) + 1;
+		shrinkerp->nr = (*shrinkerp->shrinker)(shrinkerp->nr, 
+					ratio, gfp_mask);
+	}
+
+	spin_unlock(&shrinker_lock);
+	
+	return 0;
+}
+
 /* Cal the num objs, wastage, and bytes left over for a given slab size. */
 static void kmem_cache_estimate (unsigned long gfporder, size_t size,
 		 int flags, size_t *left_over, unsigned int *num)
@@ -456,6 +509,9 @@
 
 	cache_cache.colour = left_over/cache_cache.colour_off;
 	cache_cache.colour_next = 0;
+
+	INIT_LIST_HEAD(&shrinker_list);
+	spin_lock_init(&shrinker_lock);
 }
 
 
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c	Sun Sep 15 14:28:45 2002
+++ b/mm/vmscan.c	Sun Sep 15 14:28:45 2002
@@ -607,7 +607,6 @@
 {
 	struct zone *first_classzone;
 	struct zone *zone;
-	int ratio;
 	int nr_mapped = 0;
 	int pages = nr_used_zone_pages();
 
@@ -652,10 +651,8 @@
 	 * If we're encountering mapped pages on the LRU then increase the
 	 * pressure on slab to avoid swapping.
 	 */
-	ratio = (pages / (*total_scanned + nr_mapped + 1)) + 1;
-	shrink_dcache_memory(ratio, gfp_mask);
-	shrink_icache_memory(ratio, gfp_mask);
-	shrink_dqcache_memory(ratio, gfp_mask);
+	kmem_do_shrinks(pages, *total_scanned + nr_mapped, gfp_mask);
+
 	return nr_pages;
 }
 

----------
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/

             reply	other threads:[~2002-09-15 18:36 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-09-15 18:36 Ed Tomlinson [this message]
2002-09-15 23:44 ` Andrew Morton
2002-09-15 23:54   ` Ed Tomlinson

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=200209151436.20171.tomlins@cam.org \
    --to=tomlins@cam.org \
    --cc=akpm@digeo.com \
    --cc=linux-mm@kvack.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox