aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorHou Pengyang <houpengyang@huawei.com>2017-02-16 07:34:31 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-12 00:41:51 -0500
commit4992ba2840bd40a85887a1a0e5d69f688f58f9dd (patch)
tree027132e9e7e2d9753c03683391bf1b2c5e5be1f2 /fs
parentd00d1b71d98468ad6fbee590705c27fc1241f96e (diff)
f2fs: add ovp valid_blocks check for bg gc victim to fg_gc
commit e93b9865251a0503d83fd570e7d5a7c8bc351715 upstream. For foreground gc, greedy algorithm should be adapted, which makes this formula work well: (2 * (100 / config.overprovision + 1) + 6) But currently, we fg_gc have a prior to select bg_gc victim segments to gc first, these victims are selected by cost-benefit algorithm, we can't guarantee such segments have the small valid blocks, which may destroy the f2fs rule, on the worstest case, would consume all the free segments. This patch fix this by add a filter in check_bg_victims, if segment's has # of valid blocks over overprovision ratio, skip such segments. Signed-off-by: Hou Pengyang <houpengyang@huawei.com> Reviewed-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/f2fs/f2fs.h3
-rw-r--r--fs/f2fs/gc.c22
-rw-r--r--fs/f2fs/segment.h9
3 files changed, 32 insertions, 2 deletions
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index ecc3fd0ca6bb..3a1640be7ffc 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -834,6 +834,9 @@ struct f2fs_sb_info {
834 struct f2fs_gc_kthread *gc_thread; /* GC thread */ 834 struct f2fs_gc_kthread *gc_thread; /* GC thread */
835 unsigned int cur_victim_sec; /* current victim section num */ 835 unsigned int cur_victim_sec; /* current victim section num */
836 836
837 /* threshold for converting bg victims for fg */
838 u64 fggc_threshold;
839
837 /* maximum # of trials to find a victim segment for SSR and GC */ 840 /* maximum # of trials to find a victim segment for SSR and GC */
838 unsigned int max_victim_search; 841 unsigned int max_victim_search;
839 842
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 6f14ee923acd..34a69e7ed90b 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -166,7 +166,8 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
166 p->ofs_unit = sbi->segs_per_sec; 166 p->ofs_unit = sbi->segs_per_sec;
167 } 167 }
168 168
169 if (p->max_search > sbi->max_victim_search) 169 /* we need to check every dirty segments in the FG_GC case */
170 if (gc_type != FG_GC && p->max_search > sbi->max_victim_search)
170 p->max_search = sbi->max_victim_search; 171 p->max_search = sbi->max_victim_search;
171 172
172 p->offset = sbi->last_victim[p->gc_mode]; 173 p->offset = sbi->last_victim[p->gc_mode];
@@ -199,6 +200,10 @@ static unsigned int check_bg_victims(struct f2fs_sb_info *sbi)
199 for_each_set_bit(secno, dirty_i->victim_secmap, MAIN_SECS(sbi)) { 200 for_each_set_bit(secno, dirty_i->victim_secmap, MAIN_SECS(sbi)) {
200 if (sec_usage_check(sbi, secno)) 201 if (sec_usage_check(sbi, secno))
201 continue; 202 continue;
203
204 if (no_fggc_candidate(sbi, secno))
205 continue;
206
202 clear_bit(secno, dirty_i->victim_secmap); 207 clear_bit(secno, dirty_i->victim_secmap);
203 return secno * sbi->segs_per_sec; 208 return secno * sbi->segs_per_sec;
204 } 209 }
@@ -322,13 +327,15 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
322 nsearched++; 327 nsearched++;
323 } 328 }
324 329
325
326 secno = GET_SECNO(sbi, segno); 330 secno = GET_SECNO(sbi, segno);
327 331
328 if (sec_usage_check(sbi, secno)) 332 if (sec_usage_check(sbi, secno))
329 goto next; 333 goto next;
330 if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap)) 334 if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
331 goto next; 335 goto next;
336 if (gc_type == FG_GC && p.alloc_mode == LFS &&
337 no_fggc_candidate(sbi, secno))
338 goto next;
332 339
333 cost = get_gc_cost(sbi, segno, &p); 340 cost = get_gc_cost(sbi, segno, &p);
334 341
@@ -972,5 +979,16 @@ stop:
972 979
973void build_gc_manager(struct f2fs_sb_info *sbi) 980void build_gc_manager(struct f2fs_sb_info *sbi)
974{ 981{
982 u64 main_count, resv_count, ovp_count, blocks_per_sec;
983
975 DIRTY_I(sbi)->v_ops = &default_v_ops; 984 DIRTY_I(sbi)->v_ops = &default_v_ops;
985
986 /* threshold of # of valid blocks in a section for victims of FG_GC */
987 main_count = SM_I(sbi)->main_segments << sbi->log_blocks_per_seg;
988 resv_count = SM_I(sbi)->reserved_segments << sbi->log_blocks_per_seg;
989 ovp_count = SM_I(sbi)->ovp_segments << sbi->log_blocks_per_seg;
990 blocks_per_sec = sbi->blocks_per_seg * sbi->segs_per_sec;
991
992 sbi->fggc_threshold = div_u64((main_count - ovp_count) * blocks_per_sec,
993 (main_count - resv_count));
976} 994}
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index fecb856ad874..b164f8339281 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -688,6 +688,15 @@ static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
688 - (base + 1) + type; 688 - (base + 1) + type;
689} 689}
690 690
691static inline bool no_fggc_candidate(struct f2fs_sb_info *sbi,
692 unsigned int secno)
693{
694 if (get_valid_blocks(sbi, secno, sbi->segs_per_sec) >=
695 sbi->fggc_threshold)
696 return true;
697 return false;
698}
699
691static inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int secno) 700static inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int secno)
692{ 701{
693 if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec == secno)) 702 if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec == secno))