2018-09-12 09:16:07 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2015-06-20 03:01:21 +08:00
|
|
|
/*
|
|
|
|
* f2fs shrinker support
|
|
|
|
* the basic infra was copied from fs/ubifs/shrinker.c
|
|
|
|
*
|
|
|
|
* Copyright (c) 2015 Motorola Mobility
|
|
|
|
* Copyright (c) 2015 Jaegeuk Kim <jaegeuk@kernel.org>
|
|
|
|
*/
|
|
|
|
#include <linux/fs.h>
|
|
|
|
#include <linux/f2fs_fs.h>
|
|
|
|
|
|
|
|
#include "f2fs.h"
|
2016-06-17 07:41:49 +08:00
|
|
|
#include "node.h"
|
2015-06-20 03:01:21 +08:00
|
|
|
|
|
|
|
static LIST_HEAD(f2fs_list);
|
|
|
|
static DEFINE_SPINLOCK(f2fs_list_lock);
|
|
|
|
static unsigned int shrinker_run_no;
|
|
|
|
|
2015-06-20 06:36:07 +08:00
|
|
|
static unsigned long __count_nat_entries(struct f2fs_sb_info *sbi)
|
|
|
|
{
|
2020-11-07 05:22:05 +08:00
|
|
|
return NM_I(sbi)->nat_cnt[RECLAIMABLE_NAT];
|
2015-06-20 06:36:07 +08:00
|
|
|
}
|
|
|
|
|
2015-07-28 18:33:46 +08:00
|
|
|
static unsigned long __count_free_nids(struct f2fs_sb_info *sbi)
|
|
|
|
{
|
2017-09-29 13:59:35 +08:00
|
|
|
long count = NM_I(sbi)->nid_cnt[FREE_NID] - MAX_FREE_NIDS;
|
2016-10-11 22:31:36 +08:00
|
|
|
|
|
|
|
return count > 0 ? count : 0;
|
2015-07-28 18:33:46 +08:00
|
|
|
}
|
|
|
|
|
2022-12-01 01:26:29 +08:00
|
|
|
static unsigned long __count_extent_cache(struct f2fs_sb_info *sbi,
|
|
|
|
enum extent_type type)
|
2015-06-20 04:41:23 +08:00
|
|
|
{
|
2022-12-01 01:26:29 +08:00
|
|
|
struct extent_tree_info *eti = &sbi->extent_tree[type];
|
|
|
|
|
|
|
|
return atomic_read(&eti->total_zombie_tree) +
|
|
|
|
atomic_read(&eti->total_ext_node);
|
2015-06-20 04:41:23 +08:00
|
|
|
}
|
|
|
|
|
2015-06-20 03:01:21 +08:00
|
|
|
unsigned long f2fs_shrink_count(struct shrinker *shrink,
|
|
|
|
struct shrink_control *sc)
|
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi;
|
|
|
|
struct list_head *p;
|
|
|
|
unsigned long count = 0;
|
|
|
|
|
|
|
|
spin_lock(&f2fs_list_lock);
|
|
|
|
p = f2fs_list.next;
|
|
|
|
while (p != &f2fs_list) {
|
|
|
|
sbi = list_entry(p, struct f2fs_sb_info, s_list);
|
|
|
|
|
|
|
|
/* stop f2fs_put_super */
|
|
|
|
if (!mutex_trylock(&sbi->umount_mutex)) {
|
|
|
|
p = p->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
spin_unlock(&f2fs_list_lock);
|
|
|
|
|
2022-12-01 01:26:29 +08:00
|
|
|
/* count read extent cache entries */
|
|
|
|
count += __count_extent_cache(sbi, EX_READ);
|
2015-06-20 04:41:23 +08:00
|
|
|
|
2022-12-02 09:37:15 +08:00
|
|
|
/* count block age extent cache entries */
|
|
|
|
count += __count_extent_cache(sbi, EX_BLOCK_AGE);
|
|
|
|
|
2020-02-27 19:30:05 +08:00
|
|
|
/* count clean nat cache entries */
|
2015-06-20 06:36:07 +08:00
|
|
|
count += __count_nat_entries(sbi);
|
2015-06-20 03:01:21 +08:00
|
|
|
|
2015-07-28 18:33:46 +08:00
|
|
|
/* count free nids cache entries */
|
|
|
|
count += __count_free_nids(sbi);
|
|
|
|
|
2015-06-20 03:01:21 +08:00
|
|
|
spin_lock(&f2fs_list_lock);
|
|
|
|
p = p->next;
|
|
|
|
mutex_unlock(&sbi->umount_mutex);
|
|
|
|
}
|
|
|
|
spin_unlock(&f2fs_list_lock);
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long f2fs_shrink_scan(struct shrinker *shrink,
|
|
|
|
struct shrink_control *sc)
|
|
|
|
{
|
|
|
|
unsigned long nr = sc->nr_to_scan;
|
|
|
|
struct f2fs_sb_info *sbi;
|
|
|
|
struct list_head *p;
|
|
|
|
unsigned int run_no;
|
|
|
|
unsigned long freed = 0;
|
|
|
|
|
|
|
|
spin_lock(&f2fs_list_lock);
|
|
|
|
do {
|
|
|
|
run_no = ++shrinker_run_no;
|
|
|
|
} while (run_no == 0);
|
|
|
|
p = f2fs_list.next;
|
|
|
|
while (p != &f2fs_list) {
|
|
|
|
sbi = list_entry(p, struct f2fs_sb_info, s_list);
|
|
|
|
|
|
|
|
if (sbi->shrinker_run_no == run_no)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* stop f2fs_put_super */
|
|
|
|
if (!mutex_trylock(&sbi->umount_mutex)) {
|
|
|
|
p = p->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
spin_unlock(&f2fs_list_lock);
|
|
|
|
|
|
|
|
sbi->shrinker_run_no = run_no;
|
|
|
|
|
2022-12-02 09:37:15 +08:00
|
|
|
/* shrink extent cache entries */
|
|
|
|
freed += f2fs_shrink_age_extent_tree(sbi, nr >> 2);
|
|
|
|
|
2022-12-01 01:26:29 +08:00
|
|
|
/* shrink read extent cache entries */
|
2022-12-02 09:37:15 +08:00
|
|
|
freed += f2fs_shrink_read_extent_tree(sbi, nr >> 2);
|
2015-06-20 04:41:23 +08:00
|
|
|
|
2015-06-20 06:36:07 +08:00
|
|
|
/* shrink clean nat cache entries */
|
2015-06-20 04:41:23 +08:00
|
|
|
if (freed < nr)
|
f2fs: clean up symbol namespace
As Ted reported:
"Hi, I was looking at f2fs's sources recently, and I noticed that there
is a very large number of non-static symbols which don't have a f2fs
prefix. There's well over a hundred (see attached below).
As one example, in fs/f2fs/dir.c there is:
unsigned char get_de_type(struct f2fs_dir_entry *de)
This function is clearly only useful for f2fs, but it has a generic
name. This means that if any other file system tries to have the same
symbol name, there will be a symbol conflict and the kernel would not
successfully build. It also means that when someone is looking f2fs
sources, it's not at all obvious whether a function such as
read_data_page(), invalidate_blocks(), is a generic kernel function
found in the fs, mm, or block layers, or a f2fs specific function.
You might want to fix this at some point. Hopefully Kent's bcachefs
isn't similarly using genericly named functions, since that might
cause conflicts with f2fs's functions --- but just as this would be a
problem that we would rightly insist that Kent fix, this is something
that we should have rightly insisted that f2fs should have fixed
before it was integrated into the mainline kernel.
acquire_orphan_inode
add_ino_entry
add_orphan_inode
allocate_data_block
allocate_new_segments
alloc_nid
alloc_nid_done
alloc_nid_failed
available_free_memory
...."
This patch adds "f2fs_" prefix for all non-static symbols in order to:
a) avoid conflict with other kernel generic symbols;
b) to indicate the function is f2fs specific one instead of generic
one;
Reported-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2018-05-30 00:20:41 +08:00
|
|
|
freed += f2fs_try_to_free_nats(sbi, nr - freed);
|
2015-06-20 03:01:21 +08:00
|
|
|
|
2015-07-28 18:33:46 +08:00
|
|
|
/* shrink free nids cache entries */
|
|
|
|
if (freed < nr)
|
f2fs: clean up symbol namespace
As Ted reported:
"Hi, I was looking at f2fs's sources recently, and I noticed that there
is a very large number of non-static symbols which don't have a f2fs
prefix. There's well over a hundred (see attached below).
As one example, in fs/f2fs/dir.c there is:
unsigned char get_de_type(struct f2fs_dir_entry *de)
This function is clearly only useful for f2fs, but it has a generic
name. This means that if any other file system tries to have the same
symbol name, there will be a symbol conflict and the kernel would not
successfully build. It also means that when someone is looking f2fs
sources, it's not at all obvious whether a function such as
read_data_page(), invalidate_blocks(), is a generic kernel function
found in the fs, mm, or block layers, or a f2fs specific function.
You might want to fix this at some point. Hopefully Kent's bcachefs
isn't similarly using genericly named functions, since that might
cause conflicts with f2fs's functions --- but just as this would be a
problem that we would rightly insist that Kent fix, this is something
that we should have rightly insisted that f2fs should have fixed
before it was integrated into the mainline kernel.
acquire_orphan_inode
add_ino_entry
add_orphan_inode
allocate_data_block
allocate_new_segments
alloc_nid
alloc_nid_done
alloc_nid_failed
available_free_memory
...."
This patch adds "f2fs_" prefix for all non-static symbols in order to:
a) avoid conflict with other kernel generic symbols;
b) to indicate the function is f2fs specific one instead of generic
one;
Reported-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2018-05-30 00:20:41 +08:00
|
|
|
freed += f2fs_try_to_free_nids(sbi, nr - freed);
|
2015-07-28 18:33:46 +08:00
|
|
|
|
2015-06-20 03:01:21 +08:00
|
|
|
spin_lock(&f2fs_list_lock);
|
|
|
|
p = p->next;
|
|
|
|
list_move_tail(&sbi->s_list, &f2fs_list);
|
|
|
|
mutex_unlock(&sbi->umount_mutex);
|
|
|
|
if (freed >= nr)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
spin_unlock(&f2fs_list_lock);
|
|
|
|
return freed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void f2fs_join_shrinker(struct f2fs_sb_info *sbi)
|
|
|
|
{
|
|
|
|
spin_lock(&f2fs_list_lock);
|
|
|
|
list_add_tail(&sbi->s_list, &f2fs_list);
|
|
|
|
spin_unlock(&f2fs_list_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void f2fs_leave_shrinker(struct f2fs_sb_info *sbi)
|
|
|
|
{
|
2022-12-01 01:26:29 +08:00
|
|
|
f2fs_shrink_read_extent_tree(sbi, __count_extent_cache(sbi, EX_READ));
|
2022-12-02 09:37:15 +08:00
|
|
|
f2fs_shrink_age_extent_tree(sbi,
|
|
|
|
__count_extent_cache(sbi, EX_BLOCK_AGE));
|
2015-06-20 08:53:26 +08:00
|
|
|
|
2015-06-20 03:01:21 +08:00
|
|
|
spin_lock(&f2fs_list_lock);
|
2018-12-18 19:09:24 +08:00
|
|
|
list_del_init(&sbi->s_list);
|
2015-06-20 03:01:21 +08:00
|
|
|
spin_unlock(&f2fs_list_lock);
|
|
|
|
}
|