]>
Commit | Line | Data |
---|---|---|
2658e50d JK |
1 | /* |
2 | * f2fs shrinker support | |
3 | * the basic infra was copied from fs/ubifs/shrinker.c | |
4 | * | |
5 | * Copyright (c) 2015 Motorola Mobility | |
6 | * Copyright (c) 2015 Jaegeuk Kim <jaegeuk@kernel.org> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License version 2 as | |
10 | * published by the Free Software Foundation. | |
11 | */ | |
12 | #include <linux/fs.h> | |
13 | #include <linux/f2fs_fs.h> | |
14 | ||
15 | #include "f2fs.h" | |
16 | ||
17 | static LIST_HEAD(f2fs_list); | |
18 | static DEFINE_SPINLOCK(f2fs_list_lock); | |
19 | static unsigned int shrinker_run_no; | |
20 | ||
21 | unsigned long f2fs_shrink_count(struct shrinker *shrink, | |
22 | struct shrink_control *sc) | |
23 | { | |
24 | struct f2fs_sb_info *sbi; | |
25 | struct list_head *p; | |
26 | unsigned long count = 0; | |
27 | ||
28 | spin_lock(&f2fs_list_lock); | |
29 | p = f2fs_list.next; | |
30 | while (p != &f2fs_list) { | |
31 | sbi = list_entry(p, struct f2fs_sb_info, s_list); | |
32 | ||
33 | /* stop f2fs_put_super */ | |
34 | if (!mutex_trylock(&sbi->umount_mutex)) { | |
35 | p = p->next; | |
36 | continue; | |
37 | } | |
38 | spin_unlock(&f2fs_list_lock); | |
39 | ||
40 | /* TODO: count # of objects */ | |
41 | ||
42 | spin_lock(&f2fs_list_lock); | |
43 | p = p->next; | |
44 | mutex_unlock(&sbi->umount_mutex); | |
45 | } | |
46 | spin_unlock(&f2fs_list_lock); | |
47 | return count; | |
48 | } | |
49 | ||
50 | unsigned long f2fs_shrink_scan(struct shrinker *shrink, | |
51 | struct shrink_control *sc) | |
52 | { | |
53 | unsigned long nr = sc->nr_to_scan; | |
54 | struct f2fs_sb_info *sbi; | |
55 | struct list_head *p; | |
56 | unsigned int run_no; | |
57 | unsigned long freed = 0; | |
58 | ||
59 | spin_lock(&f2fs_list_lock); | |
60 | do { | |
61 | run_no = ++shrinker_run_no; | |
62 | } while (run_no == 0); | |
63 | p = f2fs_list.next; | |
64 | while (p != &f2fs_list) { | |
65 | sbi = list_entry(p, struct f2fs_sb_info, s_list); | |
66 | ||
67 | if (sbi->shrinker_run_no == run_no) | |
68 | break; | |
69 | ||
70 | /* stop f2fs_put_super */ | |
71 | if (!mutex_trylock(&sbi->umount_mutex)) { | |
72 | p = p->next; | |
73 | continue; | |
74 | } | |
75 | spin_unlock(&f2fs_list_lock); | |
76 | ||
77 | sbi->shrinker_run_no = run_no; | |
78 | ||
79 | /* TODO: shrink caches */ | |
80 | ||
81 | spin_lock(&f2fs_list_lock); | |
82 | p = p->next; | |
83 | list_move_tail(&sbi->s_list, &f2fs_list); | |
84 | mutex_unlock(&sbi->umount_mutex); | |
85 | if (freed >= nr) | |
86 | break; | |
87 | } | |
88 | spin_unlock(&f2fs_list_lock); | |
89 | return freed; | |
90 | } | |
91 | ||
92 | void f2fs_join_shrinker(struct f2fs_sb_info *sbi) | |
93 | { | |
94 | spin_lock(&f2fs_list_lock); | |
95 | list_add_tail(&sbi->s_list, &f2fs_list); | |
96 | spin_unlock(&f2fs_list_lock); | |
97 | } | |
98 | ||
99 | void f2fs_leave_shrinker(struct f2fs_sb_info *sbi) | |
100 | { | |
101 | spin_lock(&f2fs_list_lock); | |
102 | list_del(&sbi->s_list); | |
103 | spin_unlock(&f2fs_list_lock); | |
104 | } |