linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jan Kara <jack@suse.cz>
To: Ted Tso <tytso@mit.edu>
Cc: Andreas Gruenbacher <agruenba@redhat.com>,
	linux-ext4@vger.kernel.org, Jan Kara <jack@suse.cz>
Subject: [PATCH 05/11] mbcache2: Limit cache size
Date: Mon, 22 Feb 2016 08:48:15 +0100	[thread overview]
Message-ID: <1456127301-7702-6-git-send-email-jack@suse.cz> (raw)
In-Reply-To: <1456127301-7702-1-git-send-email-jack@suse.cz>

So far number of entries in mbcache is limited only by the pressure from
the shrinker. Since too many entries degrade the hash table and
generally we expect that caching more entries has diminishing returns,
limit number of entries the same way as in the old mbcache to 16 * hash
table size.

Once we exceed the desired maximum number of entries, we schedule a
backround work to reclaim entries. If the background work cannot keep up
and the number of entries exceeds two times the desired maximum, we
reclaim some entries directly when allocating a new entry.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/mbcache2.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 5 deletions(-)

diff --git a/fs/mbcache2.c b/fs/mbcache2.c
index 5c3e1a8c38f6..3e3198d6b9d6 100644
--- a/fs/mbcache2.c
+++ b/fs/mbcache2.c
@@ -4,6 +4,7 @@
 #include <linux/list_bl.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/workqueue.h>
 #include <linux/mbcache2.h>
 
 /*
@@ -27,16 +28,29 @@ struct mb2_cache {
 	struct hlist_bl_head	*c_hash;
 	/* log2 of hash table size */
 	int			c_bucket_bits;
+	/* Maximum entries in cache to avoid degrading hash too much */
+	int			c_max_entries;
 	/* Protects c_lru_list, c_entry_count */
 	spinlock_t		c_lru_list_lock;
 	struct list_head	c_lru_list;
 	/* Number of entries in cache */
 	unsigned long		c_entry_count;
 	struct shrinker		c_shrink;
+	/* Work for shrinking when the cache has too many entries */
+	struct work_struct	c_shrink_work;
 };
 
 static struct kmem_cache *mb2_entry_cache;
 
+static unsigned long mb2_cache_shrink(struct mb2_cache *cache,
+				      unsigned int nr_to_scan);
+
+/*
+ * Number of entries to reclaim synchronously when there are too many entries
+ * in cache
+ */
+#define SYNC_SHRINK_BATCH 64
+
 /*
  * mb2_cache_entry_create - create entry in cache
  * @cache - cache where the entry should be created
@@ -55,6 +69,13 @@ int mb2_cache_entry_create(struct mb2_cache *cache, gfp_t mask, u32 key,
 	struct hlist_bl_node *dup_node;
 	struct hlist_bl_head *head;
 
+	/* Schedule background reclaim if there are too many entries */
+	if (cache->c_entry_count >= cache->c_max_entries)
+		schedule_work(&cache->c_shrink_work);
+	/* Do some sync reclaim if background reclaim cannot keep up */
+	if (cache->c_entry_count >= 2*cache->c_max_entries)
+		mb2_cache_shrink(cache, SYNC_SHRINK_BATCH);
+
 	entry = kmem_cache_alloc(mb2_entry_cache, mask);
 	if (!entry)
 		return -ENOMEM;
@@ -223,12 +244,9 @@ static unsigned long mb2_cache_count(struct shrinker *shrink,
 }
 
 /* Shrink number of entries in cache */
-static unsigned long mb2_cache_scan(struct shrinker *shrink,
-				    struct shrink_control *sc)
+static unsigned long mb2_cache_shrink(struct mb2_cache *cache,
+				      unsigned int nr_to_scan)
 {
-	int nr_to_scan = sc->nr_to_scan;
-	struct mb2_cache *cache = container_of(shrink, struct mb2_cache,
-					      c_shrink);
 	struct mb2_cache_entry *entry;
 	struct hlist_bl_head *head;
 	unsigned int shrunk = 0;
@@ -261,6 +279,25 @@ static unsigned long mb2_cache_scan(struct shrinker *shrink,
 	return shrunk;
 }
 
+static unsigned long mb2_cache_scan(struct shrinker *shrink,
+				    struct shrink_control *sc)
+{
+	int nr_to_scan = sc->nr_to_scan;
+	struct mb2_cache *cache = container_of(shrink, struct mb2_cache,
+					      c_shrink);
+	return mb2_cache_shrink(cache, nr_to_scan);
+}
+
+/* We shrink 1/X of the cache when we have too many entries in it */
+#define SHRINK_DIVISOR 16
+
+static void mb2_cache_shrink_worker(struct work_struct *work)
+{
+	struct mb2_cache *cache = container_of(work, struct mb2_cache,
+					       c_shrink_work);
+	mb2_cache_shrink(cache, cache->c_max_entries / SHRINK_DIVISOR);
+}
+
 /*
  * mb2_cache_create - create cache
  * @bucket_bits: log2 of the hash table size
@@ -280,6 +317,7 @@ struct mb2_cache *mb2_cache_create(int bucket_bits)
 	if (!cache)
 		goto err_out;
 	cache->c_bucket_bits = bucket_bits;
+	cache->c_max_entries = bucket_count << 4;
 	INIT_LIST_HEAD(&cache->c_lru_list);
 	spin_lock_init(&cache->c_lru_list_lock);
 	cache->c_hash = kmalloc(bucket_count * sizeof(struct hlist_bl_head),
@@ -296,6 +334,8 @@ struct mb2_cache *mb2_cache_create(int bucket_bits)
 	cache->c_shrink.seeks = DEFAULT_SEEKS;
 	register_shrinker(&cache->c_shrink);
 
+	INIT_WORK(&cache->c_shrink_work, mb2_cache_shrink_worker);
+
 	return cache;
 
 err_out:
-- 
2.6.2


  parent reply	other threads:[~2016-02-22  7:48 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-22  7:48 [PATCH 0/11 v3] ext[24]: MBCache rewrite Jan Kara
2016-02-22  7:48 ` [PATCH 01/11] mbcache2: Reimplement mbcache Jan Kara
2016-02-22  7:48 ` [PATCH 02/11] ext4: Convert to mbcache2 Jan Kara
2016-02-22  7:48 ` [PATCH 03/11] ext2: " Jan Kara
2016-02-22  7:48 ` [PATCH 04/11] mbcache: Remove Jan Kara
2016-02-22  7:48 ` Jan Kara [this message]
2016-02-22  7:48 ` [PATCH 06/11] mbcache2: Use referenced bit instead of LRU Jan Kara
2016-02-22  7:48 ` [PATCH 07/11] mbcache2: Rename to mbcache Jan Kara
2016-02-22  7:48 ` [PATCH 08/11] ext4: Kill ext4_mballoc_ready Jan Kara
2016-02-22  7:48 ` [PATCH 09/11] mbcache: Get rid of _e_hash_list_head Jan Kara
2016-02-22  7:48 ` [PATCH 10/11] ext4: Shortcut setting of xattr to the same value Jan Kara
2016-02-22  7:48 ` [PATCH 11/11] mbcache: Add reusable flag to cache entries Jan Kara
2016-02-22 16:31 ` [PATCH 0/11 v3] ext[24]: MBCache rewrite Theodore Ts'o
2016-02-22 18:45   ` Jan Kara

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=1456127301-7702-6-git-send-email-jack@suse.cz \
    --to=jack@suse.cz \
    --cc=agruenba@redhat.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=tytso@mit.edu \
    /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;
as well as URLs for NNTP newsgroup(s).