aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHou Pengyang <houpengyang@huawei.com>2017-02-16 07:34:31 -0500
committerJaegeuk Kim <jaegeuk@kernel.org>2017-02-23 14:28:20 -0500
commite93b9865251a0503d83fd570e7d5a7c8bc351715 (patch)
tree40675944d4c7d3a68fd3568637597095a1a6c489
parent86d54795c94532075d862aa0a79f0c981dab4bdd (diff)
f2fs: add ovp valid_blocks check for bg gc victim to fg_gc
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. Cc: <stable@vger.kernel.org> Signed-off-by: Hou Pengyang <houpengyang@huawei.com> Reviewed-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-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 7b5e287ac127..146cc71ff91c 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -890,6 +890,9 @@ struct f2fs_sb_info {
890 struct f2fs_gc_kthread *gc_thread; /* GC thread */ 890 struct f2fs_gc_kthread *gc_thread; /* GC thread */
891 unsigned int cur_victim_sec; /* current victim section num */ 891 unsigned int cur_victim_sec; /* current victim section num */
892 892
893 /* threshold for converting bg victims for fg */
894 u64 fggc_threshold;
895
893 /* maximum # of trials to find a victim segment for SSR and GC */ 896 /* maximum # of trials to find a victim segment for SSR and GC */
894 unsigned int max_victim_search; 897 unsigned int max_victim_search;
895 898
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 5ee258ebf6ca..e93aecb0138b 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
@@ -985,5 +992,16 @@ stop:
985 992
986void build_gc_manager(struct f2fs_sb_info *sbi) 993void build_gc_manager(struct f2fs_sb_info *sbi)
987{ 994{
995 u64 main_count, resv_count, ovp_count, blocks_per_sec;
996
988 DIRTY_I(sbi)->v_ops = &default_v_ops; 997 DIRTY_I(sbi)->v_ops = &default_v_ops;
998
999 /* threshold of # of valid blocks in a section for victims of FG_GC */
1000 main_count = SM_I(sbi)->main_segments << sbi->log_blocks_per_seg;
1001 resv_count = SM_I(sbi)->reserved_segments << sbi->log_blocks_per_seg;
1002 ovp_count = SM_I(sbi)->ovp_segments << sbi->log_blocks_per_seg;
1003 blocks_per_sec = sbi->blocks_per_seg * sbi->segs_per_sec;
1004
1005 sbi->fggc_threshold = div_u64((main_count - ovp_count) * blocks_per_sec,
1006 (main_count - resv_count));
989} 1007}
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 5cb5755c75d9..f4020f141d83 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -716,6 +716,15 @@ static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
716 - (base + 1) + type; 716 - (base + 1) + type;
717} 717}
718 718
719static inline bool no_fggc_candidate(struct f2fs_sb_info *sbi,
720 unsigned int secno)
721{
722 if (get_valid_blocks(sbi, secno, sbi->segs_per_sec) >=
723 sbi->fggc_threshold)
724 return true;
725 return false;
726}
727
719static inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int secno) 728static inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int secno)
720{ 729{
721 if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec == secno)) 730 if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec == secno))