Skip to content

Commit e791d00

Browse files
Daeho JeongJaegeuk Kim
authored andcommitted
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 <[email protected]> Reviewed-by: Chao Yu <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent 9a481a1 commit e791d00

File tree

7 files changed

+30
-7
lines changed

7 files changed

+30
-7
lines changed

Documentation/ABI/testing/sysfs-fs-f2fs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,3 +811,11 @@ Contact: "Daeho Jeong" <[email protected]>
811811
Description: If the percentage of free sections over total sections is under this
812812
number, F2FS boosts garbage collection for zoned devices through the
813813
background GC thread. the default number is "25".
814+
815+
What: /sys/fs/f2fs/<disk>/gc_valid_thresh_ratio
816+
Date: September 2024
817+
Contact: "Daeho Jeong" <[email protected]>
818+
Description: It controls the valid block ratio threshold not to trigger excessive GC
819+
for zoned deivces. The initial value of it is 95(%). F2FS will stop the
820+
background GC thread from intiating GC for sections having valid blocks
821+
exceeding the ratio.

fs/f2fs/f2fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3922,7 +3922,7 @@ void f2fs_destroy_garbage_collection_cache(void);
39223922
/* victim selection function for cleaning and SSR */
39233923
int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result,
39243924
int gc_type, int type, char alloc_mode,
3925-
unsigned long long age);
3925+
unsigned long long age, bool one_time);
39263926

39273927
/*
39283928
* recovery.c

fs/f2fs/gc.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi)
196196
return -ENOMEM;
197197

198198
gc_th->urgent_sleep_time = DEF_GC_THREAD_URGENT_SLEEP_TIME;
199+
gc_th->valid_thresh_ratio = DEF_GC_THREAD_VALID_THRESH_RATIO;
199200

200201
if (f2fs_sb_has_blkzoned(sbi)) {
201202
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,
396397
if (p->alloc_mode == SSR)
397398
return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
398399

400+
if (p->one_time_gc && (get_valid_blocks(sbi, segno, true) >=
401+
CAP_BLKS_PER_SEC(sbi) * sbi->gc_thread->valid_thresh_ratio /
402+
100))
403+
return UINT_MAX;
404+
399405
/* alloc_mode == LFS */
400406
if (p->gc_mode == GC_GREEDY)
401407
return get_valid_blocks(sbi, segno, true);
@@ -770,7 +776,7 @@ static int f2fs_gc_pinned_control(struct inode *inode, int gc_type,
770776
*/
771777
int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result,
772778
int gc_type, int type, char alloc_mode,
773-
unsigned long long age)
779+
unsigned long long age, bool one_time)
774780
{
775781
struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
776782
struct sit_info *sm = SIT_I(sbi);
@@ -787,6 +793,7 @@ int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result,
787793
p.alloc_mode = alloc_mode;
788794
p.age = age;
789795
p.age_threshold = sbi->am.age_threshold;
796+
p.one_time_gc = one_time;
790797

791798
retry:
792799
select_policy(sbi, gc_type, type, &p);
@@ -1698,13 +1705,14 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
16981705
}
16991706

17001707
static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim,
1701-
int gc_type)
1708+
int gc_type, bool one_time)
17021709
{
17031710
struct sit_info *sit_i = SIT_I(sbi);
17041711
int ret;
17051712

17061713
down_write(&sit_i->sentry_lock);
1707-
ret = f2fs_get_victim(sbi, victim, gc_type, NO_CHECK_TYPE, LFS, 0);
1714+
ret = f2fs_get_victim(sbi, victim, gc_type, NO_CHECK_TYPE,
1715+
LFS, 0, one_time);
17081716
up_write(&sit_i->sentry_lock);
17091717
return ret;
17101718
}
@@ -1911,7 +1919,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, struct f2fs_gc_control *gc_control)
19111919
goto stop;
19121920
}
19131921
retry:
1914-
ret = __get_victim(sbi, &segno, gc_type);
1922+
ret = __get_victim(sbi, &segno, gc_type, gc_control->one_time);
19151923
if (ret) {
19161924
/* allow to search victim from sections has pinned data */
19171925
if (ret == -ENODATA && gc_type == FG_GC &&

fs/f2fs/gc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#define DEF_GC_THREAD_CANDIDATE_RATIO 20 /* select 20% oldest sections as candidates */
2626
#define DEF_GC_THREAD_MAX_CANDIDATE_COUNT 10 /* select at most 10 sections as candidates */
2727
#define DEF_GC_THREAD_AGE_WEIGHT 60 /* age weight */
28+
#define DEF_GC_THREAD_VALID_THRESH_RATIO 95 /* do not GC over 95% valid block ratio for one time GC */
2829
#define DEFAULT_ACCURACY_CLASS 10000 /* accuracy class */
2930

3031
#define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */
@@ -65,6 +66,7 @@ struct f2fs_gc_kthread {
6566
/* for gc control for zoned devices */
6667
unsigned int no_zoned_gc_percent;
6768
unsigned int boost_zoned_gc_percent;
69+
unsigned int valid_thresh_ratio;
6870
};
6971

7072
struct gc_inode_list {

fs/f2fs/segment.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,7 +3090,8 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type,
30903090
sanity_check_seg_type(sbi, seg_type);
30913091

30923092
/* f2fs_need_SSR() already forces to do this */
3093-
if (!f2fs_get_victim(sbi, &segno, BG_GC, seg_type, alloc_mode, age)) {
3093+
if (!f2fs_get_victim(sbi, &segno, BG_GC, seg_type,
3094+
alloc_mode, age, false)) {
30943095
curseg->next_segno = segno;
30953096
return 1;
30963097
}
@@ -3117,7 +3118,8 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type,
31173118
for (; cnt-- > 0; reversed ? i-- : i++) {
31183119
if (i == seg_type)
31193120
continue;
3120-
if (!f2fs_get_victim(sbi, &segno, BG_GC, i, alloc_mode, age)) {
3121+
if (!f2fs_get_victim(sbi, &segno, BG_GC, i,
3122+
alloc_mode, age, false)) {
31213123
curseg->next_segno = segno;
31223124
return 1;
31233125
}

fs/f2fs/segment.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ struct victim_sel_policy {
188188
unsigned int min_segno; /* segment # having min. cost */
189189
unsigned long long age; /* mtime of GCed section*/
190190
unsigned long long age_threshold;/* age threshold */
191+
bool one_time_gc; /* one time GC */
191192
};
192193

193194
struct seg_entry {

fs/f2fs/sysfs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,7 @@ GC_THREAD_RW_ATTR(gc_max_sleep_time, max_sleep_time);
979979
GC_THREAD_RW_ATTR(gc_no_gc_sleep_time, no_gc_sleep_time);
980980
GC_THREAD_RW_ATTR(gc_no_zoned_gc_percent, no_zoned_gc_percent);
981981
GC_THREAD_RW_ATTR(gc_boost_zoned_gc_percent, boost_zoned_gc_percent);
982+
GC_THREAD_RW_ATTR(gc_valid_thresh_ratio, valid_thresh_ratio);
982983

983984
/* SM_INFO ATTR */
984985
SM_INFO_RW_ATTR(reclaim_segments, rec_prefree_segments);
@@ -1141,6 +1142,7 @@ static struct attribute *f2fs_attrs[] = {
11411142
ATTR_LIST(gc_no_gc_sleep_time),
11421143
ATTR_LIST(gc_no_zoned_gc_percent),
11431144
ATTR_LIST(gc_boost_zoned_gc_percent),
1145+
ATTR_LIST(gc_valid_thresh_ratio),
11441146
ATTR_LIST(gc_idle),
11451147
ATTR_LIST(gc_urgent),
11461148
ATTR_LIST(reclaim_segments),

0 commit comments

Comments
 (0)