f2fs: introduce sbi->gc_mode to determine the policy
This is to avoid sbi->gc_thread pointer access. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Родитель
107a805de8
Коммит
5b0e95398e
|
@ -1066,6 +1066,13 @@ enum {
|
||||||
MAX_TIME,
|
MAX_TIME,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
GC_NORMAL,
|
||||||
|
GC_IDLE_CB,
|
||||||
|
GC_IDLE_GREEDY,
|
||||||
|
GC_URGENT,
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
WHINT_MODE_OFF, /* not pass down write hints */
|
WHINT_MODE_OFF, /* not pass down write hints */
|
||||||
WHINT_MODE_USER, /* try to pass down hints given by users */
|
WHINT_MODE_USER, /* try to pass down hints given by users */
|
||||||
|
@ -1197,6 +1204,7 @@ struct f2fs_sb_info {
|
||||||
struct mutex gc_mutex; /* mutex for GC */
|
struct mutex gc_mutex; /* mutex for GC */
|
||||||
struct f2fs_gc_kthread *gc_thread; /* GC thread */
|
struct f2fs_gc_kthread *gc_thread; /* GC thread */
|
||||||
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 */
|
||||||
|
|
||||||
/* threshold for gc trials on pinned files */
|
/* threshold for gc trials on pinned files */
|
||||||
u64 gc_pin_file_threshold;
|
u64 gc_pin_file_threshold;
|
||||||
|
|
28
fs/f2fs/gc.c
28
fs/f2fs/gc.c
|
@ -76,7 +76,7 @@ static int gc_thread_func(void *data)
|
||||||
* invalidated soon after by user update or deletion.
|
* invalidated soon after by user update or deletion.
|
||||||
* 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 (gc_th->gc_urgent) {
|
if (sbi->gc_mode == GC_URGENT) {
|
||||||
wait_ms = gc_th->urgent_sleep_time;
|
wait_ms = gc_th->urgent_sleep_time;
|
||||||
mutex_lock(&sbi->gc_mutex);
|
mutex_lock(&sbi->gc_mutex);
|
||||||
goto do_gc;
|
goto do_gc;
|
||||||
|
@ -131,8 +131,6 @@ int start_gc_thread(struct f2fs_sb_info *sbi)
|
||||||
gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME;
|
gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME;
|
||||||
gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME;
|
gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME;
|
||||||
|
|
||||||
gc_th->gc_idle = 0;
|
|
||||||
gc_th->gc_urgent = 0;
|
|
||||||
gc_th->gc_wake= 0;
|
gc_th->gc_wake= 0;
|
||||||
|
|
||||||
sbi->gc_thread = gc_th;
|
sbi->gc_thread = gc_th;
|
||||||
|
@ -158,21 +156,19 @@ void stop_gc_thread(struct f2fs_sb_info *sbi)
|
||||||
sbi->gc_thread = NULL;
|
sbi->gc_thread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int select_gc_type(struct f2fs_gc_kthread *gc_th, int gc_type)
|
static int select_gc_type(struct f2fs_sb_info *sbi, int gc_type)
|
||||||
{
|
{
|
||||||
int gc_mode = (gc_type == BG_GC) ? GC_CB : GC_GREEDY;
|
int gc_mode = (gc_type == BG_GC) ? GC_CB : GC_GREEDY;
|
||||||
|
|
||||||
if (!gc_th)
|
switch (sbi->gc_mode) {
|
||||||
return gc_mode;
|
case GC_IDLE_CB:
|
||||||
|
gc_mode = GC_CB;
|
||||||
if (gc_th->gc_idle) {
|
break;
|
||||||
if (gc_th->gc_idle == 1)
|
case GC_IDLE_GREEDY:
|
||||||
gc_mode = GC_CB;
|
case GC_URGENT:
|
||||||
else if (gc_th->gc_idle == 2)
|
|
||||||
gc_mode = GC_GREEDY;
|
|
||||||
}
|
|
||||||
if (gc_th->gc_urgent)
|
|
||||||
gc_mode = GC_GREEDY;
|
gc_mode = GC_GREEDY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
return gc_mode;
|
return gc_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +183,7 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
|
||||||
p->max_search = dirty_i->nr_dirty[type];
|
p->max_search = dirty_i->nr_dirty[type];
|
||||||
p->ofs_unit = 1;
|
p->ofs_unit = 1;
|
||||||
} else {
|
} else {
|
||||||
p->gc_mode = select_gc_type(sbi->gc_thread, gc_type);
|
p->gc_mode = select_gc_type(sbi, gc_type);
|
||||||
p->dirty_segmap = dirty_i->dirty_segmap[DIRTY];
|
p->dirty_segmap = dirty_i->dirty_segmap[DIRTY];
|
||||||
p->max_search = dirty_i->nr_dirty[DIRTY];
|
p->max_search = dirty_i->nr_dirty[DIRTY];
|
||||||
p->ofs_unit = sbi->segs_per_sec;
|
p->ofs_unit = sbi->segs_per_sec;
|
||||||
|
@ -195,7 +191,7 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
|
||||||
|
|
||||||
/* we need to check every dirty segments in the FG_GC case */
|
/* we need to check every dirty segments in the FG_GC case */
|
||||||
if (gc_type != FG_GC &&
|
if (gc_type != FG_GC &&
|
||||||
(sbi->gc_thread && !sbi->gc_thread->gc_urgent) &&
|
(sbi->gc_mode != GC_URGENT) &&
|
||||||
p->max_search > sbi->max_victim_search)
|
p->max_search > sbi->max_victim_search)
|
||||||
p->max_search = sbi->max_victim_search;
|
p->max_search = sbi->max_victim_search;
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,6 @@ struct f2fs_gc_kthread {
|
||||||
unsigned int no_gc_sleep_time;
|
unsigned int no_gc_sleep_time;
|
||||||
|
|
||||||
/* for changing gc mode */
|
/* for changing gc mode */
|
||||||
unsigned int gc_idle;
|
|
||||||
unsigned int gc_urgent;
|
|
||||||
unsigned int gc_wake;
|
unsigned int gc_wake;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@ bool need_SSR(struct f2fs_sb_info *sbi)
|
||||||
|
|
||||||
if (test_opt(sbi, LFS))
|
if (test_opt(sbi, LFS))
|
||||||
return false;
|
return false;
|
||||||
if (sbi->gc_thread && sbi->gc_thread->gc_urgent)
|
if (sbi->gc_mode == GC_URGENT)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return free_sections(sbi) <= (node_secs + 2 * dent_secs + imeta_secs +
|
return free_sections(sbi) <= (node_secs + 2 * dent_secs + imeta_secs +
|
||||||
|
@ -1405,7 +1405,7 @@ static int issue_discard_thread(void *data)
|
||||||
if (dcc->discard_wake)
|
if (dcc->discard_wake)
|
||||||
dcc->discard_wake = 0;
|
dcc->discard_wake = 0;
|
||||||
|
|
||||||
if (sbi->gc_thread && sbi->gc_thread->gc_urgent)
|
if (sbi->gc_mode == GC_URGENT)
|
||||||
__init_discard_policy(sbi, &dpolicy, DPOLICY_FORCE, 1);
|
__init_discard_policy(sbi, &dpolicy, DPOLICY_FORCE, 1);
|
||||||
|
|
||||||
sb_start_intwrite(sbi->sb);
|
sb_start_intwrite(sbi->sb);
|
||||||
|
|
|
@ -248,16 +248,33 @@ out:
|
||||||
if (!strcmp(a->attr.name, "trim_sections"))
|
if (!strcmp(a->attr.name, "trim_sections"))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!strcmp(a->attr.name, "gc_urgent")) {
|
||||||
|
if (t >= 1) {
|
||||||
|
sbi->gc_mode = GC_URGENT;
|
||||||
|
if (sbi->gc_thread) {
|
||||||
|
wake_up_interruptible_all(
|
||||||
|
&sbi->gc_thread->gc_wait_queue_head);
|
||||||
|
wake_up_discard_thread(sbi, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sbi->gc_mode = GC_NORMAL;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
if (!strcmp(a->attr.name, "gc_idle")) {
|
||||||
|
if (t == GC_IDLE_CB)
|
||||||
|
sbi->gc_mode = GC_IDLE_CB;
|
||||||
|
else if (t == GC_IDLE_GREEDY)
|
||||||
|
sbi->gc_mode = GC_IDLE_GREEDY;
|
||||||
|
else
|
||||||
|
sbi->gc_mode = GC_NORMAL;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
*ui = t;
|
*ui = t;
|
||||||
|
|
||||||
if (!strcmp(a->attr.name, "iostat_enable") && *ui == 0)
|
if (!strcmp(a->attr.name, "iostat_enable") && *ui == 0)
|
||||||
f2fs_reset_iostat(sbi);
|
f2fs_reset_iostat(sbi);
|
||||||
if (!strcmp(a->attr.name, "gc_urgent") && t == 1 && sbi->gc_thread) {
|
|
||||||
sbi->gc_thread->gc_wake = 1;
|
|
||||||
wake_up_interruptible_all(&sbi->gc_thread->gc_wait_queue_head);
|
|
||||||
wake_up_discard_thread(sbi, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,8 +366,8 @@ F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_urgent_sleep_time,
|
||||||
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time);
|
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time);
|
||||||
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
|
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
|
||||||
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
|
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
|
||||||
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle);
|
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle, gc_mode);
|
||||||
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_urgent, gc_urgent);
|
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_urgent, gc_mode);
|
||||||
F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
|
F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
|
||||||
F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards);
|
F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards);
|
||||||
F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, discard_granularity, discard_granularity);
|
F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, discard_granularity, discard_granularity);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче