The main intention of the per-sb LRU list was to make the umount faster (commit da3bbdd4: fix soft lock up at NFS mount via per-SB LRU-list of unused dentries). Since now the per-sb shrinker on umount doesn't depend on this list this per-sb LRU is not required. And this change is also helpful for further patching where I try to make the dentry LRU lists "per-container". Signed-off-by: Pavel Emelyanov <xemul@xxxxxxxxxx> --- fs/dcache.c | 110 +++++++-------------------------------------------- fs/super.c | 1 - include/linux/fs.h | 4 -- 3 files changed, 15 insertions(+), 100 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 67d6590..1c56593 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -232,6 +232,7 @@ static void dentry_unlink_inode(struct dentry * dentry) iput(inode); } +static LIST_HEAD(dentry_lru); /* * dentry_lru_(add|del|move_tail) must be called with d_lock held. */ @@ -239,8 +240,7 @@ static void dentry_lru_add(struct dentry *dentry) { if (list_empty(&dentry->d_lru)) { spin_lock(&dcache_lru_lock); - list_add(&dentry->d_lru, &dentry->d_sb->s_dentry_lru); - dentry->d_sb->s_nr_dentry_unused++; + list_add(&dentry->d_lru, &dentry_lru); dentry_stat.nr_unused++; spin_unlock(&dcache_lru_lock); } @@ -249,7 +249,6 @@ static void dentry_lru_add(struct dentry *dentry) static void __dentry_lru_del(struct dentry *dentry) { list_del_init(&dentry->d_lru); - dentry->d_sb->s_nr_dentry_unused--; dentry_stat.nr_unused--; } @@ -839,27 +838,26 @@ static void shrink_dentry_list(struct list_head *list) } /** - * __shrink_dcache_sb - shrink the dentry LRU on a given superblock - * @sb: superblock to shrink dentry LRU. - * @count: number of entries to prune - * @flags: flags to control the dentry processing + * prune_dcache - shrink the dcache + * @count: number of entries to try to free + * + * Shrink the dcache. This is done when we need more memory, or simply when we + * need to unmount something (at which point we need to unuse all dentries). * - * If flags contains DCACHE_REFERENCED reference dentries will not be pruned. + * This function may fail to free any resources if all the dentries are in use. */ -static void __shrink_dcache_sb(struct super_block *sb, int *count, int flags) + +static void prune_dcache(int count) { /* called from prune_dcache() and shrink_dcache_parent() */ struct dentry *dentry; LIST_HEAD(referenced); LIST_HEAD(tmp); - int cnt = *count; relock: spin_lock(&dcache_lru_lock); - while (!list_empty(&sb->s_dentry_lru)) { - dentry = list_entry(sb->s_dentry_lru.prev, - struct dentry, d_lru); - BUG_ON(dentry->d_sb != sb); + while (!list_empty(&dentry_lru)) { + dentry = list_entry(dentry_lru.prev, struct dentry, d_lru); if (!spin_trylock(&dentry->d_lock)) { spin_unlock(&dcache_lru_lock); @@ -872,101 +870,23 @@ relock: * dentry has this flag set, don't free it. Clear the flag * and put it back on the LRU. */ - if (flags & DCACHE_REFERENCED && - dentry->d_flags & DCACHE_REFERENCED) { + if (dentry->d_flags & DCACHE_REFERENCED) { dentry->d_flags &= ~DCACHE_REFERENCED; list_move(&dentry->d_lru, &referenced); spin_unlock(&dentry->d_lock); } else { list_move_tail(&dentry->d_lru, &tmp); spin_unlock(&dentry->d_lock); - if (!--cnt) + if (!--count) break; } cond_resched_lock(&dcache_lru_lock); } if (!list_empty(&referenced)) - list_splice(&referenced, &sb->s_dentry_lru); + list_splice(&referenced, &dentry_lru); spin_unlock(&dcache_lru_lock); shrink_dentry_list(&tmp); - - *count = cnt; -} - -/** - * prune_dcache - shrink the dcache - * @count: number of entries to try to free - * - * Shrink the dcache. This is done when we need more memory, or simply when we - * need to unmount something (at which point we need to unuse all dentries). - * - * This function may fail to free any resources if all the dentries are in use. - */ -static void prune_dcache(int count) -{ - struct super_block *sb, *p = NULL; - int w_count; - int unused = dentry_stat.nr_unused; - int prune_ratio; - int pruned; - - if (unused == 0 || count == 0) - return; - if (count >= unused) - prune_ratio = 1; - else - prune_ratio = unused / count; - spin_lock(&sb_lock); - list_for_each_entry(sb, &super_blocks, s_list) { - if (list_empty(&sb->s_instances)) - continue; - if (sb->s_nr_dentry_unused == 0) - continue; - sb->s_count++; - /* Now, we reclaim unused dentrins with fairness. - * We reclaim them same percentage from each superblock. - * We calculate number of dentries to scan on this sb - * as follows, but the implementation is arranged to avoid - * overflows: - * number of dentries to scan on this sb = - * count * (number of dentries on this sb / - * number of dentries in the machine) - */ - spin_unlock(&sb_lock); - if (prune_ratio != 1) - w_count = (sb->s_nr_dentry_unused / prune_ratio) + 1; - else - w_count = sb->s_nr_dentry_unused; - pruned = w_count; - /* - * We need to be sure this filesystem isn't being unmounted, - * otherwise we could race with generic_shutdown_super(), and - * end up holding a reference to an inode while the filesystem - * is unmounted. So we try to get s_umount, and make sure - * s_root isn't NULL. - */ - if (down_read_trylock(&sb->s_umount)) { - if ((sb->s_root != NULL) && - (!list_empty(&sb->s_dentry_lru))) { - __shrink_dcache_sb(sb, &w_count, - DCACHE_REFERENCED); - pruned -= w_count; - } - up_read(&sb->s_umount); - } - spin_lock(&sb_lock); - if (p) - __put_super(p); - count -= pruned; - p = sb; - /* more work left to do? */ - if (count <= 0) - break; - } - if (p) - __put_super(p); - spin_unlock(&sb_lock); } /** diff --git a/fs/super.c b/fs/super.c index 0293e6e..e598558 100644 --- a/fs/super.c +++ b/fs/super.c @@ -74,7 +74,6 @@ static struct super_block *alloc_super(struct file_system_type *type) INIT_LIST_HEAD(&s->s_instances); INIT_HLIST_BL_HEAD(&s->s_anon); INIT_LIST_HEAD(&s->s_inodes); - INIT_LIST_HEAD(&s->s_dentry_lru); init_rwsem(&s->s_umount); mutex_init(&s->s_lock); lockdep_set_class(&s->s_umount, &type->s_umount_key); diff --git a/include/linux/fs.h b/include/linux/fs.h index 63b4b7a..a236ea3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1387,10 +1387,6 @@ struct super_block { #else struct list_head s_files; #endif - /* s_dentry_lru, s_nr_dentry_unused protected by dcache.c lru locks */ - struct list_head s_dentry_lru; /* unused dentry lru */ - int s_nr_dentry_unused; /* # of dentry on lru */ - struct block_device *s_bdev; struct backing_dev_info *s_bdi; struct mtd_info *s_mtd; -- 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