mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 05:02:12 +00:00
f2fs: add valid block ratio not to do excessive GC for one time GC
We need to introduce a valid block ratio threshold not to trigger excessive GC for zoned deivces. The initial value of it is 95%. So, F2FS will stop the thread from intiating GC for sections having valid blocks exceeding the ratio. Signed-off-by: Daeho Jeong <daehojeong@google.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
9a481a1c16
commit
e791d00bd0
@ -811,3 +811,11 @@ Contact: "Daeho Jeong" <daehojeong@google.com>
|
||||
Description: If the percentage of free sections over total sections is under this
|
||||
number, F2FS boosts garbage collection for zoned devices through the
|
||||
background GC thread. the default number is "25".
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/gc_valid_thresh_ratio
|
||||
Date: September 2024
|
||||
Contact: "Daeho Jeong" <daehojeong@google.com>
|
||||
Description: It controls the valid block ratio threshold not to trigger excessive GC
|
||||
for zoned deivces. The initial value of it is 95(%). F2FS will stop the
|
||||
background GC thread from intiating GC for sections having valid blocks
|
||||
exceeding the ratio.
|
||||
|
@ -3922,7 +3922,7 @@ void f2fs_destroy_garbage_collection_cache(void);
|
||||
/* victim selection function for cleaning and SSR */
|
||||
int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result,
|
||||
int gc_type, int type, char alloc_mode,
|
||||
unsigned long long age);
|
||||
unsigned long long age, bool one_time);
|
||||
|
||||
/*
|
||||
* recovery.c
|
||||
|
16
fs/f2fs/gc.c
16
fs/f2fs/gc.c
@ -196,6 +196,7 @@ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi)
|
||||
return -ENOMEM;
|
||||
|
||||
gc_th->urgent_sleep_time = DEF_GC_THREAD_URGENT_SLEEP_TIME;
|
||||
gc_th->valid_thresh_ratio = DEF_GC_THREAD_VALID_THRESH_RATIO;
|
||||
|
||||
if (f2fs_sb_has_blkzoned(sbi)) {
|
||||
gc_th->min_sleep_time = DEF_GC_THREAD_MIN_SLEEP_TIME_ZONED;
|
||||
@ -396,6 +397,11 @@ static inline unsigned int get_gc_cost(struct f2fs_sb_info *sbi,
|
||||
if (p->alloc_mode == SSR)
|
||||
return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
|
||||
|
||||
if (p->one_time_gc && (get_valid_blocks(sbi, segno, true) >=
|
||||
CAP_BLKS_PER_SEC(sbi) * sbi->gc_thread->valid_thresh_ratio /
|
||||
100))
|
||||
return UINT_MAX;
|
||||
|
||||
/* alloc_mode == LFS */
|
||||
if (p->gc_mode == GC_GREEDY)
|
||||
return get_valid_blocks(sbi, segno, true);
|
||||
@ -770,7 +776,7 @@ static int f2fs_gc_pinned_control(struct inode *inode, int gc_type,
|
||||
*/
|
||||
int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result,
|
||||
int gc_type, int type, char alloc_mode,
|
||||
unsigned long long age)
|
||||
unsigned long long age, bool one_time)
|
||||
{
|
||||
struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
|
||||
struct sit_info *sm = SIT_I(sbi);
|
||||
@ -787,6 +793,7 @@ int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result,
|
||||
p.alloc_mode = alloc_mode;
|
||||
p.age = age;
|
||||
p.age_threshold = sbi->am.age_threshold;
|
||||
p.one_time_gc = one_time;
|
||||
|
||||
retry:
|
||||
select_policy(sbi, gc_type, type, &p);
|
||||
@ -1698,13 +1705,14 @@ next_step:
|
||||
}
|
||||
|
||||
static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim,
|
||||
int gc_type)
|
||||
int gc_type, bool one_time)
|
||||
{
|
||||
struct sit_info *sit_i = SIT_I(sbi);
|
||||
int ret;
|
||||
|
||||
down_write(&sit_i->sentry_lock);
|
||||
ret = f2fs_get_victim(sbi, victim, gc_type, NO_CHECK_TYPE, LFS, 0);
|
||||
ret = f2fs_get_victim(sbi, victim, gc_type, NO_CHECK_TYPE,
|
||||
LFS, 0, one_time);
|
||||
up_write(&sit_i->sentry_lock);
|
||||
return ret;
|
||||
}
|
||||
@ -1911,7 +1919,7 @@ gc_more:
|
||||
goto stop;
|
||||
}
|
||||
retry:
|
||||
ret = __get_victim(sbi, &segno, gc_type);
|
||||
ret = __get_victim(sbi, &segno, gc_type, gc_control->one_time);
|
||||
if (ret) {
|
||||
/* allow to search victim from sections has pinned data */
|
||||
if (ret == -ENODATA && gc_type == FG_GC &&
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define DEF_GC_THREAD_CANDIDATE_RATIO 20 /* select 20% oldest sections as candidates */
|
||||
#define DEF_GC_THREAD_MAX_CANDIDATE_COUNT 10 /* select at most 10 sections as candidates */
|
||||
#define DEF_GC_THREAD_AGE_WEIGHT 60 /* age weight */
|
||||
#define DEF_GC_THREAD_VALID_THRESH_RATIO 95 /* do not GC over 95% valid block ratio for one time GC */
|
||||
#define DEFAULT_ACCURACY_CLASS 10000 /* accuracy class */
|
||||
|
||||
#define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */
|
||||
@ -65,6 +66,7 @@ struct f2fs_gc_kthread {
|
||||
/* for gc control for zoned devices */
|
||||
unsigned int no_zoned_gc_percent;
|
||||
unsigned int boost_zoned_gc_percent;
|
||||
unsigned int valid_thresh_ratio;
|
||||
};
|
||||
|
||||
struct gc_inode_list {
|
||||
|
@ -3090,7 +3090,8 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type,
|
||||
sanity_check_seg_type(sbi, seg_type);
|
||||
|
||||
/* f2fs_need_SSR() already forces to do this */
|
||||
if (!f2fs_get_victim(sbi, &segno, BG_GC, seg_type, alloc_mode, age)) {
|
||||
if (!f2fs_get_victim(sbi, &segno, BG_GC, seg_type,
|
||||
alloc_mode, age, false)) {
|
||||
curseg->next_segno = segno;
|
||||
return 1;
|
||||
}
|
||||
@ -3117,7 +3118,8 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type,
|
||||
for (; cnt-- > 0; reversed ? i-- : i++) {
|
||||
if (i == seg_type)
|
||||
continue;
|
||||
if (!f2fs_get_victim(sbi, &segno, BG_GC, i, alloc_mode, age)) {
|
||||
if (!f2fs_get_victim(sbi, &segno, BG_GC, i,
|
||||
alloc_mode, age, false)) {
|
||||
curseg->next_segno = segno;
|
||||
return 1;
|
||||
}
|
||||
|
@ -188,6 +188,7 @@ struct victim_sel_policy {
|
||||
unsigned int min_segno; /* segment # having min. cost */
|
||||
unsigned long long age; /* mtime of GCed section*/
|
||||
unsigned long long age_threshold;/* age threshold */
|
||||
bool one_time_gc; /* one time GC */
|
||||
};
|
||||
|
||||
struct seg_entry {
|
||||
|
@ -979,6 +979,7 @@ GC_THREAD_RW_ATTR(gc_max_sleep_time, max_sleep_time);
|
||||
GC_THREAD_RW_ATTR(gc_no_gc_sleep_time, no_gc_sleep_time);
|
||||
GC_THREAD_RW_ATTR(gc_no_zoned_gc_percent, no_zoned_gc_percent);
|
||||
GC_THREAD_RW_ATTR(gc_boost_zoned_gc_percent, boost_zoned_gc_percent);
|
||||
GC_THREAD_RW_ATTR(gc_valid_thresh_ratio, valid_thresh_ratio);
|
||||
|
||||
/* SM_INFO ATTR */
|
||||
SM_INFO_RW_ATTR(reclaim_segments, rec_prefree_segments);
|
||||
@ -1141,6 +1142,7 @@ static struct attribute *f2fs_attrs[] = {
|
||||
ATTR_LIST(gc_no_gc_sleep_time),
|
||||
ATTR_LIST(gc_no_zoned_gc_percent),
|
||||
ATTR_LIST(gc_boost_zoned_gc_percent),
|
||||
ATTR_LIST(gc_valid_thresh_ratio),
|
||||
ATTR_LIST(gc_idle),
|
||||
ATTR_LIST(gc_urgent),
|
||||
ATTR_LIST(reclaim_segments),
|
||||
|
Loading…
Reference in New Issue
Block a user