Commit 325163e9 authored by Daeho Jeong's avatar Daeho Jeong Committed by Jaegeuk Kim

f2fs: add gc_urgent_high_remaining sysfs node

Added a new sysfs node called gc_urgent_high_remaining. The user can
set the trial count limit for GC urgent high mode with this value. If
GC thread gets to the limit, the mode will turn back to GC normal mode.
By default, the value is zero, which means there is no limit like before.
Signed-off-by: default avatarDaeho Jeong <daehojeong@google.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 77900c45
...@@ -533,3 +533,10 @@ Description: With "mode=fragment:block" mount options, we can scatter block allo ...@@ -533,3 +533,10 @@ Description: With "mode=fragment:block" mount options, we can scatter block allo
f2fs will allocate 1..<max_fragment_chunk> blocks in a chunk and make a hole f2fs will allocate 1..<max_fragment_chunk> blocks in a chunk and make a hole
in the length of 1..<max_fragment_hole> by turns. This value can be set in the length of 1..<max_fragment_hole> by turns. This value can be set
between 1..512 and the default value is 4. between 1..512 and the default value is 4.
What: /sys/fs/f2fs/<disk>/gc_urgent_high_remaining
Date: December 2021
Contact: "Daeho Jeong" <daehojeong@google.com>
Description: You can set the trial count limit for GC urgent high mode with this value.
If GC thread gets to the limit, the mode will turn back to GC normal mode.
By default, the value is zero, which means there is no limit like before.
...@@ -1683,6 +1683,9 @@ struct f2fs_sb_info { ...@@ -1683,6 +1683,9 @@ struct f2fs_sb_info {
unsigned int cur_victim_sec; /* current victim section num */ unsigned int cur_victim_sec; /* current victim section num */
unsigned int gc_mode; /* current GC state */ unsigned int gc_mode; /* current GC state */
unsigned int next_victim_seg[2]; /* next segment in victim section */ unsigned int next_victim_seg[2]; /* next segment in victim section */
spinlock_t gc_urgent_high_lock;
bool gc_urgent_high_limited; /* indicates having limited trial count */
unsigned int gc_urgent_high_remaining; /* remaining trial count for GC_URGENT_HIGH */
/* for skip statistic */ /* for skip statistic */
unsigned int atomic_files; /* # of opened atomic file */ unsigned int atomic_files; /* # of opened atomic file */
......
...@@ -92,6 +92,18 @@ static int gc_thread_func(void *data) ...@@ -92,6 +92,18 @@ static int gc_thread_func(void *data)
* So, I'd like to wait some time to collect dirty segments. * So, I'd like to wait some time to collect dirty segments.
*/ */
if (sbi->gc_mode == GC_URGENT_HIGH) { if (sbi->gc_mode == GC_URGENT_HIGH) {
spin_lock(&sbi->gc_urgent_high_lock);
if (sbi->gc_urgent_high_limited) {
if (!sbi->gc_urgent_high_remaining) {
sbi->gc_urgent_high_limited = false;
spin_unlock(&sbi->gc_urgent_high_lock);
sbi->gc_mode = GC_NORMAL;
continue;
}
sbi->gc_urgent_high_remaining--;
}
spin_unlock(&sbi->gc_urgent_high_lock);
wait_ms = gc_th->urgent_sleep_time; wait_ms = gc_th->urgent_sleep_time;
down_write(&sbi->gc_lock); down_write(&sbi->gc_lock);
goto do_gc; goto do_gc;
......
...@@ -3548,6 +3548,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi) ...@@ -3548,6 +3548,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
sbi->seq_file_ra_mul = MIN_RA_MUL; sbi->seq_file_ra_mul = MIN_RA_MUL;
sbi->max_fragment_chunk = DEF_FRAGMENT_SIZE; sbi->max_fragment_chunk = DEF_FRAGMENT_SIZE;
sbi->max_fragment_hole = DEF_FRAGMENT_SIZE; sbi->max_fragment_hole = DEF_FRAGMENT_SIZE;
spin_lock_init(&sbi->gc_urgent_high_lock);
sbi->dir_level = DEF_DIR_LEVEL; sbi->dir_level = DEF_DIR_LEVEL;
sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL; sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL;
......
...@@ -487,6 +487,15 @@ static ssize_t __sbi_store(struct f2fs_attr *a, ...@@ -487,6 +487,15 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
return count; return count;
} }
if (!strcmp(a->attr.name, "gc_urgent_high_remaining")) {
spin_lock(&sbi->gc_urgent_high_lock);
sbi->gc_urgent_high_limited = t == 0 ? false : true;
sbi->gc_urgent_high_remaining = t;
spin_unlock(&sbi->gc_urgent_high_lock);
return count;
}
#ifdef CONFIG_F2FS_IOSTAT #ifdef CONFIG_F2FS_IOSTAT
if (!strcmp(a->attr.name, "iostat_enable")) { if (!strcmp(a->attr.name, "iostat_enable")) {
sbi->iostat_enable = !!t; sbi->iostat_enable = !!t;
...@@ -742,6 +751,7 @@ F2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type); ...@@ -742,6 +751,7 @@ F2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type);
#endif #endif
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, data_io_flag, data_io_flag); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, data_io_flag, data_io_flag);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, node_io_flag, node_io_flag); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, node_io_flag, node_io_flag);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_urgent_high_remaining, gc_urgent_high_remaining);
F2FS_RW_ATTR(CPRC_INFO, ckpt_req_control, ckpt_thread_ioprio, ckpt_thread_ioprio); F2FS_RW_ATTR(CPRC_INFO, ckpt_req_control, ckpt_thread_ioprio, ckpt_thread_ioprio);
F2FS_GENERAL_RO_ATTR(dirty_segments); F2FS_GENERAL_RO_ATTR(dirty_segments);
F2FS_GENERAL_RO_ATTR(free_segments); F2FS_GENERAL_RO_ATTR(free_segments);
...@@ -855,6 +865,7 @@ static struct attribute *f2fs_attrs[] = { ...@@ -855,6 +865,7 @@ static struct attribute *f2fs_attrs[] = {
#endif #endif
ATTR_LIST(data_io_flag), ATTR_LIST(data_io_flag),
ATTR_LIST(node_io_flag), ATTR_LIST(node_io_flag),
ATTR_LIST(gc_urgent_high_remaining),
ATTR_LIST(ckpt_thread_ioprio), ATTR_LIST(ckpt_thread_ioprio),
ATTR_LIST(dirty_segments), ATTR_LIST(dirty_segments),
ATTR_LIST(free_segments), ATTR_LIST(free_segments),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment