1 // SPDX-License-Identifier: GPL-2.0
3 * f2fs shrinker support
4 * the basic infra was copied from fs/ubifs/shrinker.c
6 * Copyright (c) 2015 Motorola Mobility
7 * Copyright (c) 2015 Jaegeuk Kim <jaegeuk@kernel.org>
10 #include <linux/f2fs_fs.h>
15 static LIST_HEAD(f2fs_list
);
16 static DEFINE_SPINLOCK(f2fs_list_lock
);
17 static unsigned int shrinker_run_no
;
19 static unsigned long __count_nat_entries(struct f2fs_sb_info
*sbi
)
21 return NM_I(sbi
)->nat_cnt
[RECLAIMABLE_NAT
];
24 static unsigned long __count_free_nids(struct f2fs_sb_info
*sbi
)
26 long count
= NM_I(sbi
)->nid_cnt
[FREE_NID
] - MAX_FREE_NIDS
;
28 return count
> 0 ? count
: 0;
31 static unsigned long __count_extent_cache(struct f2fs_sb_info
*sbi
)
33 return atomic_read(&sbi
->total_zombie_tree
) +
34 atomic_read(&sbi
->total_ext_node
);
37 unsigned long f2fs_shrink_count(struct shrinker
*shrink
,
38 struct shrink_control
*sc
)
40 struct f2fs_sb_info
*sbi
;
42 unsigned long count
= 0;
44 spin_lock(&f2fs_list_lock
);
46 while (p
!= &f2fs_list
) {
47 sbi
= list_entry(p
, struct f2fs_sb_info
, s_list
);
49 /* stop f2fs_put_super */
50 if (!mutex_trylock(&sbi
->umount_mutex
)) {
54 spin_unlock(&f2fs_list_lock
);
56 /* count extent cache entries */
57 count
+= __count_extent_cache(sbi
);
59 /* count clean nat cache entries */
60 count
+= __count_nat_entries(sbi
);
62 /* count free nids cache entries */
63 count
+= __count_free_nids(sbi
);
65 spin_lock(&f2fs_list_lock
);
67 mutex_unlock(&sbi
->umount_mutex
);
69 spin_unlock(&f2fs_list_lock
);
73 unsigned long f2fs_shrink_scan(struct shrinker
*shrink
,
74 struct shrink_control
*sc
)
76 unsigned long nr
= sc
->nr_to_scan
;
77 struct f2fs_sb_info
*sbi
;
80 unsigned long freed
= 0;
82 spin_lock(&f2fs_list_lock
);
84 run_no
= ++shrinker_run_no
;
85 } while (run_no
== 0);
87 while (p
!= &f2fs_list
) {
88 sbi
= list_entry(p
, struct f2fs_sb_info
, s_list
);
90 if (sbi
->shrinker_run_no
== run_no
)
93 /* stop f2fs_put_super */
94 if (!mutex_trylock(&sbi
->umount_mutex
)) {
98 spin_unlock(&f2fs_list_lock
);
100 sbi
->shrinker_run_no
= run_no
;
102 /* shrink extent cache entries */
103 freed
+= f2fs_shrink_extent_tree(sbi
, nr
>> 1);
105 /* shrink clean nat cache entries */
107 freed
+= f2fs_try_to_free_nats(sbi
, nr
- freed
);
109 /* shrink free nids cache entries */
111 freed
+= f2fs_try_to_free_nids(sbi
, nr
- freed
);
113 spin_lock(&f2fs_list_lock
);
115 list_move_tail(&sbi
->s_list
, &f2fs_list
);
116 mutex_unlock(&sbi
->umount_mutex
);
120 spin_unlock(&f2fs_list_lock
);
124 void f2fs_join_shrinker(struct f2fs_sb_info
*sbi
)
126 spin_lock(&f2fs_list_lock
);
127 list_add_tail(&sbi
->s_list
, &f2fs_list
);
128 spin_unlock(&f2fs_list_lock
);
131 void f2fs_leave_shrinker(struct f2fs_sb_info
*sbi
)
133 f2fs_shrink_extent_tree(sbi
, __count_extent_cache(sbi
));
135 spin_lock(&f2fs_list_lock
);
136 list_del_init(&sbi
->s_list
);
137 spin_unlock(&f2fs_list_lock
);