diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 131 |
1 files changed, 81 insertions, 50 deletions
diff --git a/fs/super.c b/fs/super.c index 68307c029228..0225c20f8770 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,46 +69,62 @@ 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 && 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, sc->nid); |
76 | |||
77 | total_objects = sb->s_nr_dentry_unused + | ||
78 | sb->s_nr_inodes_unused + fs_objects + 1; | ||
79 | |||
80 | if (sc->nr_to_scan) { | ||
81 | int dentries; | ||
82 | int inodes; | ||
83 | |||
84 | /* proportion the scan between the caches */ | ||
85 | dentries = (sc->nr_to_scan * sb->s_nr_dentry_unused) / | ||
86 | total_objects; | ||
87 | inodes = (sc->nr_to_scan * sb->s_nr_inodes_unused) / | ||
88 | total_objects; | ||
89 | if (fs_objects) | ||
90 | fs_objects = (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 | 80 | ||
99 | if (fs_objects && sb->s_op->free_cached_objects) { | 81 | inodes = list_lru_count_node(&sb->s_inode_lru, sc->nid); |
100 | sb->s_op->free_cached_objects(sb, fs_objects); | 82 | dentries = list_lru_count_node(&sb->s_dentry_lru, sc->nid); |
101 | fs_objects = sb->s_op->nr_cached_objects(sb); | 83 | total_objects = dentries + inodes + fs_objects + 1; |
102 | } | 84 | |
103 | total_objects = sb->s_nr_dentry_unused + | 85 | /* proportion the scan between the caches */ |
104 | sb->s_nr_inodes_unused + fs_objects; | 86 | dentries = mult_frac(sc->nr_to_scan, dentries, total_objects); |
87 | inodes = mult_frac(sc->nr_to_scan, inodes, total_objects); | ||
88 | |||
89 | /* | ||
90 | * prune the dcache first as the icache is pinned by it, then | ||
91 | * prune the icache, followed by the filesystem specific caches | ||
92 | */ | ||
93 | freed = prune_dcache_sb(sb, dentries, sc->nid); | ||
94 | freed += prune_icache_sb(sb, inodes, sc->nid); | ||
95 | |||
96 | if (fs_objects) { | ||
97 | fs_objects = mult_frac(sc->nr_to_scan, fs_objects, | ||
98 | total_objects); | ||
99 | freed += sb->s_op->free_cached_objects(sb, fs_objects, | ||
100 | sc->nid); | ||
105 | } | 101 | } |
106 | 102 | ||
107 | total_objects = (total_objects / 100) * sysctl_vfs_cache_pressure; | 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 | sc->nid); | ||
121 | |||
122 | total_objects += list_lru_count_node(&sb->s_dentry_lru, | ||
123 | sc->nid); | ||
124 | total_objects += list_lru_count_node(&sb->s_inode_lru, | ||
125 | sc->nid); | ||
126 | |||
127 | total_objects = vfs_pressure_ratio(total_objects); | ||
108 | drop_super(sb); | 128 | drop_super(sb); |
109 | return total_objects; | 129 | return total_objects; |
110 | } | 130 | } |
@@ -152,15 +172,9 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
152 | static const struct super_operations default_op; | 172 | static const struct super_operations default_op; |
153 | 173 | ||
154 | if (s) { | 174 | if (s) { |
155 | if (security_sb_alloc(s)) { | 175 | if (security_sb_alloc(s)) |
156 | /* | 176 | goto out_free_sb; |
157 | * We cannot call security_sb_free() without | 177 | |
158 | * security_sb_alloc() succeeding. So bail out manually | ||
159 | */ | ||
160 | kfree(s); | ||
161 | s = NULL; | ||
162 | goto out; | ||
163 | } | ||
164 | #ifdef CONFIG_SMP | 178 | #ifdef CONFIG_SMP |
165 | s->s_files = alloc_percpu(struct list_head); | 179 | s->s_files = alloc_percpu(struct list_head); |
166 | if (!s->s_files) | 180 | if (!s->s_files) |
@@ -181,9 +195,12 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
181 | INIT_HLIST_NODE(&s->s_instances); | 195 | INIT_HLIST_NODE(&s->s_instances); |
182 | INIT_HLIST_BL_HEAD(&s->s_anon); | 196 | INIT_HLIST_BL_HEAD(&s->s_anon); |
183 | INIT_LIST_HEAD(&s->s_inodes); | 197 | INIT_LIST_HEAD(&s->s_inodes); |
184 | INIT_LIST_HEAD(&s->s_dentry_lru); | 198 | |
185 | INIT_LIST_HEAD(&s->s_inode_lru); | 199 | if (list_lru_init(&s->s_dentry_lru)) |
186 | spin_lock_init(&s->s_inode_lru_lock); | 200 | goto err_out; |
201 | if (list_lru_init(&s->s_inode_lru)) | ||
202 | goto err_out_dentry_lru; | ||
203 | |||
187 | INIT_LIST_HEAD(&s->s_mounts); | 204 | INIT_LIST_HEAD(&s->s_mounts); |
188 | init_rwsem(&s->s_umount); | 205 | init_rwsem(&s->s_umount); |
189 | lockdep_set_class(&s->s_umount, &type->s_umount_key); | 206 | lockdep_set_class(&s->s_umount, &type->s_umount_key); |
@@ -216,11 +233,16 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
216 | s->cleancache_poolid = -1; | 233 | s->cleancache_poolid = -1; |
217 | 234 | ||
218 | s->s_shrink.seeks = DEFAULT_SEEKS; | 235 | s->s_shrink.seeks = DEFAULT_SEEKS; |
219 | s->s_shrink.shrink = prune_super; | 236 | s->s_shrink.scan_objects = super_cache_scan; |
237 | s->s_shrink.count_objects = super_cache_count; | ||
220 | s->s_shrink.batch = 1024; | 238 | s->s_shrink.batch = 1024; |
239 | s->s_shrink.flags = SHRINKER_NUMA_AWARE; | ||
221 | } | 240 | } |
222 | out: | 241 | out: |
223 | return s; | 242 | return s; |
243 | |||
244 | err_out_dentry_lru: | ||
245 | list_lru_destroy(&s->s_dentry_lru); | ||
224 | err_out: | 246 | err_out: |
225 | security_sb_free(s); | 247 | security_sb_free(s); |
226 | #ifdef CONFIG_SMP | 248 | #ifdef CONFIG_SMP |
@@ -228,6 +250,7 @@ err_out: | |||
228 | free_percpu(s->s_files); | 250 | free_percpu(s->s_files); |
229 | #endif | 251 | #endif |
230 | destroy_sb_writers(s); | 252 | destroy_sb_writers(s); |
253 | out_free_sb: | ||
231 | kfree(s); | 254 | kfree(s); |
232 | s = NULL; | 255 | s = NULL; |
233 | goto out; | 256 | goto out; |
@@ -241,6 +264,8 @@ err_out: | |||
241 | */ | 264 | */ |
242 | static inline void destroy_super(struct super_block *s) | 265 | static inline void destroy_super(struct super_block *s) |
243 | { | 266 | { |
267 | list_lru_destroy(&s->s_dentry_lru); | ||
268 | list_lru_destroy(&s->s_inode_lru); | ||
244 | #ifdef CONFIG_SMP | 269 | #ifdef CONFIG_SMP |
245 | free_percpu(s->s_files); | 270 | free_percpu(s->s_files); |
246 | #endif | 271 | #endif |
@@ -300,6 +325,7 @@ void deactivate_locked_super(struct super_block *s) | |||
300 | 325 | ||
301 | /* caches are now gone, we can safely kill the shrinker now */ | 326 | /* caches are now gone, we can safely kill the shrinker now */ |
302 | unregister_shrinker(&s->s_shrink); | 327 | unregister_shrinker(&s->s_shrink); |
328 | |||
303 | put_filesystem(fs); | 329 | put_filesystem(fs); |
304 | put_super(s); | 330 | put_super(s); |
305 | } else { | 331 | } else { |
@@ -414,6 +440,11 @@ void generic_shutdown_super(struct super_block *sb) | |||
414 | 440 | ||
415 | evict_inodes(sb); | 441 | evict_inodes(sb); |
416 | 442 | ||
443 | if (sb->s_dio_done_wq) { | ||
444 | destroy_workqueue(sb->s_dio_done_wq); | ||
445 | sb->s_dio_done_wq = NULL; | ||
446 | } | ||
447 | |||
417 | if (sop->put_super) | 448 | if (sop->put_super) |
418 | sop->put_super(sb); | 449 | sop->put_super(sb); |
419 | 450 | ||