f2fs: sysfs: introduce critical_task_priority

This patch introduces /sys/fs/f2fs/<disk>/critical_task_priority, w/
this new sysfs interface, we can tune priority of f2fs_ckpt thread and
f2fs_gc thread.

Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Chao Yu 2026-02-04 11:05:01 +08:00 committed by Jaegeuk Kim
parent bc367775f6
commit 52190933c3
6 changed files with 34 additions and 0 deletions

View File

@ -987,3 +987,11 @@ Contact: "Chao Yu" <chao@kernel.org>
Description: f2fs can tune priority of thread which has entered into critical region covered by Description: f2fs can tune priority of thread which has entered into critical region covered by
f2fs rwsemphore lock. This sysfs entry can be used to control priority value, the f2fs rwsemphore lock. This sysfs entry can be used to control priority value, the
range is [100,139], by default the value is 120. range is [100,139], by default the value is 120.
What: /sys/fs/f2fs/<disk>/critical_task_priority
Date: February 2026
Contact: "Chao Yu" <chao@kernel.org>
Description: It can be used to tune priority of f2fs critical task, e.g. f2fs_ckpt, f2fs_gc
threads, limitation as below:
- it requires user has CAP_SYS_NICE capability.
- the range is [100, 139], by default the value is 100.

View File

@ -2158,6 +2158,8 @@ int f2fs_start_ckpt_thread(struct f2fs_sb_info *sbi)
} }
set_task_ioprio(cprc->f2fs_issue_ckpt, cprc->ckpt_thread_ioprio); set_task_ioprio(cprc->f2fs_issue_ckpt, cprc->ckpt_thread_ioprio);
set_user_nice(cprc->f2fs_issue_ckpt,
PRIO_TO_NICE(sbi->critical_task_priority));
return 0; return 0;
} }

View File

@ -1593,6 +1593,7 @@ enum node_type {
#define MAX_LOCK_ELAPSED_TIME 500 #define MAX_LOCK_ELAPSED_TIME 500
#define F2FS_DEFAULT_TASK_PRIORITY (DEFAULT_PRIO) #define F2FS_DEFAULT_TASK_PRIORITY (DEFAULT_PRIO)
#define F2FS_CRITICAL_TASK_PRIORITY NICE_TO_PRIO(0)
static inline int f2fs_test_bit(unsigned int nr, char *addr); static inline int f2fs_test_bit(unsigned int nr, char *addr);
static inline void f2fs_set_bit(unsigned int nr, char *addr); static inline void f2fs_set_bit(unsigned int nr, char *addr);
@ -2010,6 +2011,9 @@ struct f2fs_sb_info {
/* adjust priority for task which is in critical region covered by lock */ /* adjust priority for task which is in critical region covered by lock */
unsigned int lock_duration_priority; unsigned int lock_duration_priority;
/* priority for critical task, e.g. f2fs_ckpt, f2fs_gc threads */
long critical_task_priority;
#ifdef CONFIG_F2FS_FS_COMPRESSION #ifdef CONFIG_F2FS_FS_COMPRESSION
struct kmem_cache *page_array_slab; /* page array entry */ struct kmem_cache *page_array_slab; /* page array entry */
unsigned int page_array_slab_size; /* default page array slab size */ unsigned int page_array_slab_size; /* default page array slab size */

View File

@ -234,6 +234,8 @@ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi)
return err; return err;
} }
set_user_nice(gc_th->f2fs_gc_task,
PRIO_TO_NICE(sbi->critical_task_priority));
return 0; return 0;
} }

View File

@ -4340,6 +4340,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
sbi->max_lock_elapsed_time = MAX_LOCK_ELAPSED_TIME; sbi->max_lock_elapsed_time = MAX_LOCK_ELAPSED_TIME;
sbi->adjust_lock_priority = 0; sbi->adjust_lock_priority = 0;
sbi->lock_duration_priority = F2FS_DEFAULT_TASK_PRIORITY; sbi->lock_duration_priority = F2FS_DEFAULT_TASK_PRIORITY;
sbi->critical_task_priority = F2FS_CRITICAL_TASK_PRIORITY;
sbi->sum_blocksize = f2fs_sb_has_packed_ssa(sbi) ? sbi->sum_blocksize = f2fs_sb_has_packed_ssa(sbi) ?
4096 : sbi->blocksize; 4096 : sbi->blocksize;

View File

@ -969,6 +969,21 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
return count; return count;
} }
if (!strcmp(a->attr.name, "critical_task_priority")) {
if (t < NICE_TO_PRIO(MIN_NICE) || t > NICE_TO_PRIO(MAX_NICE))
return -EINVAL;
if (!capable(CAP_SYS_NICE))
return -EPERM;
sbi->critical_task_priority = t;
if (sbi->cprc_info.f2fs_issue_ckpt)
set_user_nice(sbi->cprc_info.f2fs_issue_ckpt,
PRIO_TO_NICE(sbi->critical_task_priority));
if (sbi->gc_thread && sbi->gc_thread->f2fs_gc_task)
set_user_nice(sbi->gc_thread->f2fs_gc_task,
PRIO_TO_NICE(sbi->critical_task_priority));
return count;
}
__sbi_store_value(a, sbi, ptr + a->offset, t); __sbi_store_value(a, sbi, ptr + a->offset, t);
return count; return count;
@ -1288,6 +1303,7 @@ F2FS_SBI_GENERAL_RW_ATTR(bggc_io_aware);
F2FS_SBI_GENERAL_RW_ATTR(max_lock_elapsed_time); F2FS_SBI_GENERAL_RW_ATTR(max_lock_elapsed_time);
F2FS_SBI_GENERAL_RW_ATTR(lock_duration_priority); F2FS_SBI_GENERAL_RW_ATTR(lock_duration_priority);
F2FS_SBI_GENERAL_RW_ATTR(adjust_lock_priority); F2FS_SBI_GENERAL_RW_ATTR(adjust_lock_priority);
F2FS_SBI_GENERAL_RW_ATTR(critical_task_priority);
/* STAT_INFO ATTR */ /* STAT_INFO ATTR */
#ifdef CONFIG_F2FS_STAT_FS #ifdef CONFIG_F2FS_STAT_FS
@ -1496,6 +1512,7 @@ static struct attribute *f2fs_attrs[] = {
ATTR_LIST(max_lock_elapsed_time), ATTR_LIST(max_lock_elapsed_time),
ATTR_LIST(lock_duration_priority), ATTR_LIST(lock_duration_priority),
ATTR_LIST(adjust_lock_priority), ATTR_LIST(adjust_lock_priority),
ATTR_LIST(critical_task_priority),
NULL, NULL,
}; };
ATTRIBUTE_GROUPS(f2fs); ATTRIBUTE_GROUPS(f2fs);