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 <xemul@xxxxxxxxxx> --- 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 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html