4d57b86dd8
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>
143 lines
3.3 KiB
C
143 lines
3.3 KiB
C
/*
|
|
* 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>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
#include <linux/fs.h>
|
|
#include <linux/f2fs_fs.h>
|
|
|
|
#include "f2fs.h"
|
|
#include "node.h"
|
|
|
|
static LIST_HEAD(f2fs_list);
|
|
static DEFINE_SPINLOCK(f2fs_list_lock);
|
|
static unsigned int shrinker_run_no;
|
|
|
|
static unsigned long __count_nat_entries(struct f2fs_sb_info *sbi)
|
|
{
|
|
long count = NM_I(sbi)->nat_cnt - NM_I(sbi)->dirty_nat_cnt;
|
|
|
|
return count > 0 ? count : 0;
|
|
}
|
|
|
|
static unsigned long __count_free_nids(struct f2fs_sb_info *sbi)
|
|
{
|
|
long count = NM_I(sbi)->nid_cnt[FREE_NID] - MAX_FREE_NIDS;
|
|
|
|
return count > 0 ? count : 0;
|
|
}
|
|
|
|
static unsigned long __count_extent_cache(struct f2fs_sb_info *sbi)
|
|
{
|
|
return atomic_read(&sbi->total_zombie_tree) +
|
|
atomic_read(&sbi->total_ext_node);
|
|
}
|
|
|
|
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);
|
|
|
|
/* count extent cache entries */
|
|
count += __count_extent_cache(sbi);
|
|
|
|
/* shrink clean nat cache entries */
|
|
count += __count_nat_entries(sbi);
|
|
|
|
/* count free nids cache entries */
|
|
count += __count_free_nids(sbi);
|
|
|
|
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;
|
|
|
|
/* shrink extent cache entries */
|
|
freed += f2fs_shrink_extent_tree(sbi, nr >> 1);
|
|
|
|
/* shrink clean nat cache entries */
|
|
if (freed < nr)
|
|
freed += f2fs_try_to_free_nats(sbi, nr - freed);
|
|
|
|
/* shrink free nids cache entries */
|
|
if (freed < nr)
|
|
freed += f2fs_try_to_free_nids(sbi, nr - freed);
|
|
|
|
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)
|
|
{
|
|
f2fs_shrink_extent_tree(sbi, __count_extent_cache(sbi));
|
|
|
|
spin_lock(&f2fs_list_lock);
|
|
list_del(&sbi->s_list);
|
|
spin_unlock(&f2fs_list_lock);
|
|
}
|