diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 80 |
1 files changed, 49 insertions, 31 deletions
diff --git a/fs/super.c b/fs/super.c index 3c5318694ccd..8aa2660642b9 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -53,11 +53,15 @@ static char *sb_writers_name[SB_FREEZE_LEVELS] = { | |||
53 | * shrinker path and that leads to deadlock on the shrinker_rwsem. Hence we | 53 | * shrinker path and that leads to deadlock on the shrinker_rwsem. Hence we |
54 | * take a passive reference to the superblock to avoid this from occurring. | 54 | * take a passive reference to the superblock to avoid this from occurring. |
55 | */ | 55 | */ |
56 | static int prune_super(struct shrinker *shrink, struct shrink_control *sc) | 56 | static unsigned long super_cache_scan(struct shrinker *shrink, |
57 | struct shrink_control *sc) | ||
57 | { | 58 | { |
58 | struct super_block *sb; | 59 | struct super_block *sb; |
59 | int fs_objects = 0; | 60 | long fs_objects = 0; |
60 | int total_objects; | 61 | long total_objects; |
62 | long freed = 0; | ||
63 | long dentries; | ||
64 | long inodes; | ||
61 | 65 | ||
62 | sb = container_of(shrink, struct super_block, s_shrink); | 66 | sb = container_of(shrink, struct super_block, s_shrink); |
63 | 67 | ||
@@ -65,11 +69,11 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc) | |||
65 | * Deadlock avoidance. We may hold various FS locks, and we don't want | 69 | * Deadlock avoidance. We may hold various FS locks, and we don't want |
66 | * to recurse into the FS that called us in clear_inode() and friends.. | 70 | * to recurse into the FS that called us in clear_inode() and friends.. |
67 | */ | 71 | */ |
68 | if (sc->nr_to_scan && !(sc->gfp_mask & __GFP_FS)) | 72 | if (!(sc->gfp_mask & __GFP_FS)) |
69 | return -1; | 73 | return SHRINK_STOP; |
70 | 74 | ||
71 | if (!grab_super_passive(sb)) | 75 | if (!grab_super_passive(sb)) |
72 | return -1; | 76 | return SHRINK_STOP; |
73 | 77 | ||
74 | if (sb->s_op->nr_cached_objects) | 78 | if (sb->s_op->nr_cached_objects) |
75 | fs_objects = sb->s_op->nr_cached_objects(sb); | 79 | fs_objects = sb->s_op->nr_cached_objects(sb); |
@@ -77,33 +81,46 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc) | |||
77 | total_objects = sb->s_nr_dentry_unused + | 81 | total_objects = sb->s_nr_dentry_unused + |
78 | sb->s_nr_inodes_unused + fs_objects + 1; | 82 | sb->s_nr_inodes_unused + fs_objects + 1; |
79 | 83 | ||
80 | if (sc->nr_to_scan) { | 84 | /* proportion the scan between the caches */ |
81 | int dentries; | 85 | dentries = mult_frac(sc->nr_to_scan, sb->s_nr_dentry_unused, |
82 | int inodes; | 86 | total_objects); |
83 | 87 | inodes = mult_frac(sc->nr_to_scan, sb->s_nr_inodes_unused, | |
84 | /* proportion the scan between the caches */ | 88 | total_objects); |
85 | dentries = mult_frac(sc->nr_to_scan, sb->s_nr_dentry_unused, | ||
86 | total_objects); | ||
87 | inodes = mult_frac(sc->nr_to_scan, sb->s_nr_inodes_unused, | ||
88 | total_objects); | ||
89 | if (fs_objects) | ||
90 | fs_objects = mult_frac(sc->nr_to_scan, fs_objects, | ||
91 | total_objects); | ||
92 | /* | ||
93 | * prune the dcache first as the icache is pinned by it, then | ||
94 | * prune the icache, followed by the filesystem specific caches | ||
95 | */ | ||
96 | prune_dcache_sb(sb, dentries); | ||
97 | prune_icache_sb(sb, inodes); | ||
98 | 89 | ||
99 | if (fs_objects && sb->s_op->free_cached_objects) { | 90 | /* |
100 | sb->s_op->free_cached_objects(sb, fs_objects); | 91 | * prune the dcache first as the icache is pinned by it, then |
101 | fs_objects = sb->s_op->nr_cached_objects(sb); | 92 | * prune the icache, followed by the filesystem specific caches |
102 | } | 93 | */ |
103 | total_objects = sb->s_nr_dentry_unused + | 94 | freed = prune_dcache_sb(sb, dentries); |
104 | sb->s_nr_inodes_unused + fs_objects; | 95 | freed += prune_icache_sb(sb, inodes); |
96 | |||
97 | if (fs_objects) { | ||
98 | fs_objects = mult_frac(sc->nr_to_scan, fs_objects, | ||
99 | total_objects); | ||
100 | freed += sb->s_op->free_cached_objects(sb, fs_objects); | ||
105 | } | 101 | } |
106 | 102 | ||
103 | drop_super(sb); | ||
104 | return freed; | ||
105 | } | ||
106 | |||
107 | static unsigned long super_cache_count(struct shrinker *shrink, | ||
108 | struct shrink_control *sc) | ||
109 | { | ||
110 | struct super_block *sb; | ||
111 | long total_objects = 0; | ||
112 | |||
113 | sb = container_of(shrink, struct super_block, s_shrink); | ||
114 | |||
115 | if (!grab_super_passive(sb)) | ||
116 | return 0; | ||
117 | |||
118 | if (sb->s_op && sb->s_op->nr_cached_objects) | ||
119 | total_objects = sb->s_op->nr_cached_objects(sb); | ||
120 | |||
121 | total_objects += sb->s_nr_dentry_unused; | ||
122 | total_objects += sb->s_nr_inodes_unused; | ||
123 | |||
107 | total_objects = vfs_pressure_ratio(total_objects); | 124 | total_objects = vfs_pressure_ratio(total_objects); |
108 | drop_super(sb); | 125 | drop_super(sb); |
109 | return total_objects; | 126 | return total_objects; |
@@ -211,7 +228,8 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
211 | s->cleancache_poolid = -1; | 228 | s->cleancache_poolid = -1; |
212 | 229 | ||
213 | s->s_shrink.seeks = DEFAULT_SEEKS; | 230 | s->s_shrink.seeks = DEFAULT_SEEKS; |
214 | s->s_shrink.shrink = prune_super; | 231 | s->s_shrink.scan_objects = super_cache_scan; |
232 | s->s_shrink.count_objects = super_cache_count; | ||
215 | s->s_shrink.batch = 1024; | 233 | s->s_shrink.batch = 1024; |
216 | } | 234 | } |
217 | out: | 235 | out: |