aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-07-08 00:14:44 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2011-07-20 20:47:41 -0400
commit0e1fdafd93980eac62e778798549ce0f6073905c (patch)
treea8b21525d195d436fa738e9a470e64eaa21e6736 /fs
parent4f8c19fdf3f97402b68f058b1c72a6c7166c9e59 (diff)
superblock: add filesystem shrinker operations
Now we have a per-superblock shrinker implementation, we can add a filesystem specific callout to it to allow filesystem internal caches to be shrunk by the superblock shrinker. Rather than perpetuate the multipurpose shrinker callback API (i.e. nr_to_scan == 0 meaning "tell me how many objects freeable in the cache), two operations will be added. The first will return the number of objects that are freeable, the second is the actual shrinker call. Signed-off-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/super.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/fs/super.c b/fs/super.c
index 37a75410079e..5101f0544960 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -48,7 +48,8 @@ DEFINE_SPINLOCK(sb_lock);
48static int prune_super(struct shrinker *shrink, struct shrink_control *sc) 48static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
49{ 49{
50 struct super_block *sb; 50 struct super_block *sb;
51 int count; 51 int fs_objects = 0;
52 int total_objects;
52 53
53 sb = container_of(shrink, struct super_block, s_shrink); 54 sb = container_of(shrink, struct super_block, s_shrink);
54 55
@@ -62,22 +63,42 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
62 if (!grab_super_passive(sb)) 63 if (!grab_super_passive(sb))
63 return -1; 64 return -1;
64 65
65 if (sc->nr_to_scan) { 66 if (sb->s_op && sb->s_op->nr_cached_objects)
66 /* proportion the scan between the two caches */ 67 fs_objects = sb->s_op->nr_cached_objects(sb);
67 int total; 68
69 total_objects = sb->s_nr_dentry_unused +
70 sb->s_nr_inodes_unused + fs_objects + 1;
68 71
69 total = sb->s_nr_dentry_unused + sb->s_nr_inodes_unused + 1; 72 if (sc->nr_to_scan) {
70 count = (sc->nr_to_scan * sb->s_nr_dentry_unused) / total; 73 int dentries;
74 int inodes;
75
76 /* proportion the scan between the caches */
77 dentries = (sc->nr_to_scan * sb->s_nr_dentry_unused) /
78 total_objects;
79 inodes = (sc->nr_to_scan * sb->s_nr_inodes_unused) /
80 total_objects;
81 if (fs_objects)
82 fs_objects = (sc->nr_to_scan * fs_objects) /
83 total_objects;
84 /*
85 * prune the dcache first as the icache is pinned by it, then
86 * prune the icache, followed by the filesystem specific caches
87 */
88 prune_dcache_sb(sb, dentries);
89 prune_icache_sb(sb, inodes);
71 90
72 /* prune dcache first as icache is pinned by it */ 91 if (fs_objects && sb->s_op->free_cached_objects) {
73 prune_dcache_sb(sb, count); 92 sb->s_op->free_cached_objects(sb, fs_objects);
74 prune_icache_sb(sb, sc->nr_to_scan - count); 93 fs_objects = sb->s_op->nr_cached_objects(sb);
94 }
95 total_objects = sb->s_nr_dentry_unused +
96 sb->s_nr_inodes_unused + fs_objects;
75 } 97 }
76 98
77 count = ((sb->s_nr_dentry_unused + sb->s_nr_inodes_unused) / 100) 99 total_objects = (total_objects / 100) * sysctl_vfs_cache_pressure;
78 * sysctl_vfs_cache_pressure;
79 drop_super(sb); 100 drop_super(sb);
80 return count; 101 return total_objects;
81} 102}
82 103
83/** 104/**