Commit 5b0e9539 authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs: introduce sbi->gc_mode to determine the policy

This is to avoid sbi->gc_thread pointer access.
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 107a805d
...@@ -1066,6 +1066,13 @@ enum { ...@@ -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 { ...@@ -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;
......
...@@ -76,7 +76,7 @@ static int gc_thread_func(void *data) ...@@ -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) ...@@ -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) ...@@ -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:
if (gc_th->gc_idle) {
if (gc_th->gc_idle == 1)
gc_mode = GC_CB; gc_mode = GC_CB;
else if (gc_th->gc_idle == 2) break;
case GC_IDLE_GREEDY:
case GC_URGENT:
gc_mode = GC_GREEDY; gc_mode = GC_GREEDY;
break;
} }
if (gc_th->gc_urgent)
gc_mode = GC_GREEDY;
return gc_mode; return gc_mode;
} }
...@@ -187,7 +183,7 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type, ...@@ -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, ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a, ...@@ -248,16 +248,33 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
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, ...@@ -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);
......
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