f2fs: shrink nat_cache entries
[deliverable/linux.git] / fs / f2fs / shrinker.c
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 static unsigned long __count_nat_entries(struct f2fs_sb_info *sbi)
22 {
23 return NM_I(sbi)->nat_cnt - NM_I(sbi)->dirty_nat_cnt;
24 }
25
26 unsigned long f2fs_shrink_count(struct shrinker *shrink,
27 struct shrink_control *sc)
28 {
29 struct f2fs_sb_info *sbi;
30 struct list_head *p;
31 unsigned long count = 0;
32
33 spin_lock(&f2fs_list_lock);
34 p = f2fs_list.next;
35 while (p != &f2fs_list) {
36 sbi = list_entry(p, struct f2fs_sb_info, s_list);
37
38 /* stop f2fs_put_super */
39 if (!mutex_trylock(&sbi->umount_mutex)) {
40 p = p->next;
41 continue;
42 }
43 spin_unlock(&f2fs_list_lock);
44
45 /* shrink clean nat cache entries */
46 count += __count_nat_entries(sbi);
47
48 spin_lock(&f2fs_list_lock);
49 p = p->next;
50 mutex_unlock(&sbi->umount_mutex);
51 }
52 spin_unlock(&f2fs_list_lock);
53 return count;
54 }
55
56 unsigned long f2fs_shrink_scan(struct shrinker *shrink,
57 struct shrink_control *sc)
58 {
59 unsigned long nr = sc->nr_to_scan;
60 struct f2fs_sb_info *sbi;
61 struct list_head *p;
62 unsigned int run_no;
63 unsigned long freed = 0;
64
65 spin_lock(&f2fs_list_lock);
66 do {
67 run_no = ++shrinker_run_no;
68 } while (run_no == 0);
69 p = f2fs_list.next;
70 while (p != &f2fs_list) {
71 sbi = list_entry(p, struct f2fs_sb_info, s_list);
72
73 if (sbi->shrinker_run_no == run_no)
74 break;
75
76 /* stop f2fs_put_super */
77 if (!mutex_trylock(&sbi->umount_mutex)) {
78 p = p->next;
79 continue;
80 }
81 spin_unlock(&f2fs_list_lock);
82
83 sbi->shrinker_run_no = run_no;
84
85 /* shrink clean nat cache entries */
86 freed += try_to_free_nats(sbi, nr);
87
88 spin_lock(&f2fs_list_lock);
89 p = p->next;
90 list_move_tail(&sbi->s_list, &f2fs_list);
91 mutex_unlock(&sbi->umount_mutex);
92 if (freed >= nr)
93 break;
94 }
95 spin_unlock(&f2fs_list_lock);
96 return freed;
97 }
98
99 void f2fs_join_shrinker(struct f2fs_sb_info *sbi)
100 {
101 spin_lock(&f2fs_list_lock);
102 list_add_tail(&sbi->s_list, &f2fs_list);
103 spin_unlock(&f2fs_list_lock);
104 }
105
106 void f2fs_leave_shrinker(struct f2fs_sb_info *sbi)
107 {
108 spin_lock(&f2fs_list_lock);
109 list_del(&sbi->s_list);
110 spin_unlock(&f2fs_list_lock);
111 }
This page took 0.039005 seconds and 5 git commands to generate.