From mboxrd@z Thu Jan 1 00:00:00 1970 From: Pavel Emelyanov Subject: [PATCH 11/13] vfs: Make shrink_dcache_memory prune dcache from all mobs Date: Tue, 03 May 2011 16:19:42 +0400 Message-ID: <4DBFF2DE.8070700@parallels.com> References: <4DBFF1AD.90303@parallels.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Cc: linux-fsdevel To: Hugh Dickins , Nick Piggin , Andrea Arcangeli , Rik van Riel , Dave Hansen , Alexa Return-path: Received: from mailhub.sw.ru ([195.214.232.25]:13722 "EHLO relay.sw.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752600Ab1ECMTs (ORCPT ); Tue, 3 May 2011 08:19:48 -0400 In-Reply-To: <4DBFF1AD.90303@parallels.com> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: For that the list of mobs and their number is introduced. When the shrink_dcache_memory is called it will srhrink dcache from each mob in the system. By now I shrink equal count of dentries from each mob, but I'm open for discussions of better policies. Signed-off-by: Pavel Emelyanov --- fs/dcache.c | 35 ++++++++++++++++++++++++++++++++++- include/linux/dcache.h | 1 + 2 files changed, 35 insertions(+), 1 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index bdacea3..01e3464 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -124,6 +124,9 @@ struct dentry_stat_t dentry_stat = { }; static struct dentry_mob init_dentry_mob; +static LIST_HEAD(dentry_mobs); +static unsigned int dentry_mobs_nr = 1; +static DEFINE_SPINLOCK(dcache_mobs_lock); #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS) int proc_nr_dentry(ctl_table *table, int write, void __user *buffer, @@ -889,6 +892,25 @@ relock: return shrink_dentry_list(&tmp); } +static void prune_dcache_mobs(int nr) +{ + int nr_per_mob; + struct dentry_mob *mob; + + nr_per_mob = nr / dentry_mobs_nr; + if (nr_per_mob == 0) + nr_per_mob = 16; + + while (nr--) { + spin_lock(&dcache_mobs_lock); + mob = list_first_entry(&dentry_mobs, struct dentry_mob, mobs); + list_move_tail(&mob->mobs, &dentry_mobs); + spin_unlock(&dcache_mobs_lock); + + prune_dcache(mob, nr_per_mob); + } +} + /** * shrink_dcache_sb - shrink dcache for a superblock * @sb: superblock @@ -1063,7 +1085,7 @@ static int shrink_dcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) if (nr) { if (!(gfp_mask & __GFP_FS)) return -1; - prune_dcache(&init_dentry_mob, nr); + prune_dcache_mobs(nr); } return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; @@ -2874,6 +2896,11 @@ static struct dentry_mob *create_mob(struct dentry_mob *cur) static void destroy_mob(struct dentry_mob *mob) { + spin_lock(&dcache_mobs_lock); + list_del(&mob->mobs); + dentry_mobs_nr--; + spin_unlock(&dcache_mobs_lock); + if (percpu_counter_sum(&mob->nr_dentry) != 0) BUG(); if (!list_empty(&mob->dentry_lru)) @@ -3000,6 +3027,11 @@ int dcache_new_mob(struct dentry *root) percpu_counter_inc(&dmob->nr_dentry); spin_unlock(&root->d_lock); + spin_lock(&dcache_mobs_lock); + list_add(&dmob->mobs, &dentry_mobs); + dentry_mobs_nr++; + spin_unlock(&dcache_mobs_lock); + if (old != NULL) destroy_mob(old); @@ -3077,6 +3109,7 @@ static void __init dcache_init(void) percpu_counter_init(&init_dentry_mob.nr_dentry, 0); init_dentry_mob.nr_dentry_max = 80 * 1024 * 1024 / sizeof(struct dentry); INIT_LIST_HEAD(&init_dentry_mob.dentry_lru); + list_add_tail(&init_dentry_mob.mobs, &dentry_mobs); printk("nr_dentry_max = %lu\n", init_dentry_mob.nr_dentry_max); diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 0d13966..7b1fdc1 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -52,6 +52,7 @@ struct dentry_mob { struct percpu_counter nr_dentry; unsigned long nr_dentry_max; struct list_head dentry_lru; + struct list_head mobs; }; struct dentry; -- 1.5.5.6