From 29ebf5dd65e7a916737057d0e96c695cc3c9ba78 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Fri, 8 Jul 2011 14:14:44 +1000 Subject: [PATCH] --- yaml --- r: 257370 b: refs/heads/master c: 0e1fdafd93980eac62e778798549ce0f6073905c h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Documentation/filesystems/vfs.txt | 16 +++++++++ trunk/fs/super.c | 45 ++++++++++++++++++------- trunk/include/linux/fs.h | 2 ++ 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/[refs] b/[refs] index b6ae01b17fe6..38ced3ad875d 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 4f8c19fdf3f97402b68f058b1c72a6c7166c9e59 +refs/heads/master: 0e1fdafd93980eac62e778798549ce0f6073905c diff --git a/trunk/Documentation/filesystems/vfs.txt b/trunk/Documentation/filesystems/vfs.txt index d56151fe77dc..fd24f34f120f 100644 --- a/trunk/Documentation/filesystems/vfs.txt +++ b/trunk/Documentation/filesystems/vfs.txt @@ -229,6 +229,8 @@ struct super_operations { ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t); ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t); + int (*nr_cached_objects)(struct super_block *); + void (*free_cached_objects)(struct super_block *, int); }; All methods are called without any locks being held, unless otherwise @@ -301,6 +303,20 @@ or bottom half). quota_write: called by the VFS to write to filesystem quota file. + nr_cached_objects: called by the sb cache shrinking function for the + filesystem to return the number of freeable cached objects it contains. + Optional. + + free_cache_objects: called by the sb cache shrinking function for the + filesystem to scan the number of objects indicated to try to free them. + Optional, but any filesystem implementing this method needs to also + implement ->nr_cached_objects for it to be called correctly. + + We can't do anything with any errors that the filesystem might + encountered, hence the void return type. This will never be called if + the VM is trying to reclaim under GFP_NOFS conditions, hence this + method does not need to handle that situation itself. + Whoever sets up the inode is responsible for filling in the "i_op" field. This is a pointer to a "struct inode_operations" which describes the methods that can be performed on individual inodes. diff --git a/trunk/fs/super.c b/trunk/fs/super.c index 37a75410079e..5101f0544960 100644 --- a/trunk/fs/super.c +++ b/trunk/fs/super.c @@ -48,7 +48,8 @@ DEFINE_SPINLOCK(sb_lock); static int prune_super(struct shrinker *shrink, struct shrink_control *sc) { struct super_block *sb; - int count; + int fs_objects = 0; + int total_objects; sb = container_of(shrink, struct super_block, s_shrink); @@ -62,22 +63,42 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc) if (!grab_super_passive(sb)) return -1; - if (sc->nr_to_scan) { - /* proportion the scan between the two caches */ - int total; + if (sb->s_op && sb->s_op->nr_cached_objects) + fs_objects = sb->s_op->nr_cached_objects(sb); + + total_objects = sb->s_nr_dentry_unused + + sb->s_nr_inodes_unused + fs_objects + 1; - total = sb->s_nr_dentry_unused + sb->s_nr_inodes_unused + 1; - count = (sc->nr_to_scan * sb->s_nr_dentry_unused) / total; + if (sc->nr_to_scan) { + int dentries; + int inodes; + + /* proportion the scan between the caches */ + dentries = (sc->nr_to_scan * sb->s_nr_dentry_unused) / + total_objects; + inodes = (sc->nr_to_scan * sb->s_nr_inodes_unused) / + total_objects; + if (fs_objects) + fs_objects = (sc->nr_to_scan * fs_objects) / + total_objects; + /* + * prune the dcache first as the icache is pinned by it, then + * prune the icache, followed by the filesystem specific caches + */ + prune_dcache_sb(sb, dentries); + prune_icache_sb(sb, inodes); - /* prune dcache first as icache is pinned by it */ - prune_dcache_sb(sb, count); - prune_icache_sb(sb, sc->nr_to_scan - count); + if (fs_objects && sb->s_op->free_cached_objects) { + sb->s_op->free_cached_objects(sb, fs_objects); + fs_objects = sb->s_op->nr_cached_objects(sb); + } + total_objects = sb->s_nr_dentry_unused + + sb->s_nr_inodes_unused + fs_objects; } - count = ((sb->s_nr_dentry_unused + sb->s_nr_inodes_unused) / 100) - * sysctl_vfs_cache_pressure; + total_objects = (total_objects / 100) * sysctl_vfs_cache_pressure; drop_super(sb); - return count; + return total_objects; } /** diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index d7f35e90b84a..1393742bba9b 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -1655,6 +1655,8 @@ struct super_operations { ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t); #endif int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t); + int (*nr_cached_objects)(struct super_block *); + void (*free_cached_objects)(struct super_block *, int); }; /*