aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/gc.c
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2013-03-31 00:26:03 -0400
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-04-03 04:27:49 -0400
commit5ec4e49f9bd753e2a6857a96e01f8ae5ff00b459 (patch)
tree25938d3e5e3e5c9bbb37de1ee6c2cd6ad23071a8 /fs/f2fs/gc.c
parent33afa7fde0defbb362328233e600e052d0a22cd5 (diff)
f2fs: change GC bitmaps to apply the section granularity
This patch removes a bitmap for victim segments selected by foreground GC, and modifies the other bitmap for victim segments selected by background GC. 1) foreground GC bitmap : We don't need to manage this, since we just only one previous victim section number instead of the whole victim history. The f2fs uses the victim section number in order not to allocate currently GC'ed section to current active logs. 2) background GC bitmap : This bitmap is used to avoid selecting victims repeatedly by background GCs. In addition, the victims are able to be selected by foreground GCs, since there is no need to read victim blocks during foreground GCs. By the fact that the foreground GC reclaims segments in a section unit, it'd be better to manage this bitmap based on the section granularity. Reviewed-by: Namjae Jeon <namjae.jeon@samsung.com> Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/gc.c')
-rw-r--r--fs/f2fs/gc.c43
1 files changed, 24 insertions, 19 deletions
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 2e3eb2d4fc30..09b8a907400b 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -160,18 +160,21 @@ static unsigned int get_max_cost(struct f2fs_sb_info *sbi,
160static unsigned int check_bg_victims(struct f2fs_sb_info *sbi) 160static unsigned int check_bg_victims(struct f2fs_sb_info *sbi)
161{ 161{
162 struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); 162 struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
163 unsigned int segno; 163 unsigned int hint = 0;
164 unsigned int secno;
164 165
165 /* 166 /*
166 * If the gc_type is FG_GC, we can select victim segments 167 * If the gc_type is FG_GC, we can select victim segments
167 * selected by background GC before. 168 * selected by background GC before.
168 * Those segments guarantee they have small valid blocks. 169 * Those segments guarantee they have small valid blocks.
169 */ 170 */
170 segno = find_next_bit(dirty_i->victim_segmap[BG_GC], 171next:
171 TOTAL_SEGS(sbi), 0); 172 secno = find_next_bit(dirty_i->victim_secmap, TOTAL_SECS(sbi), hint++);
172 if (segno < TOTAL_SEGS(sbi)) { 173 if (secno < TOTAL_SECS(sbi)) {
173 clear_bit(segno, dirty_i->victim_segmap[BG_GC]); 174 if (sec_usage_check(sbi, secno))
174 return segno; 175 goto next;
176 clear_bit(secno, dirty_i->victim_secmap);
177 return secno * sbi->segs_per_sec;
175 } 178 }
176 return NULL_SEGNO; 179 return NULL_SEGNO;
177} 180}
@@ -234,7 +237,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
234{ 237{
235 struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); 238 struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
236 struct victim_sel_policy p; 239 struct victim_sel_policy p;
237 unsigned int segno; 240 unsigned int secno;
238 int nsearched = 0; 241 int nsearched = 0;
239 242
240 p.alloc_mode = alloc_mode; 243 p.alloc_mode = alloc_mode;
@@ -253,6 +256,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
253 256
254 while (1) { 257 while (1) {
255 unsigned long cost; 258 unsigned long cost;
259 unsigned int segno;
256 260
257 segno = find_next_bit(p.dirty_segmap, 261 segno = find_next_bit(p.dirty_segmap,
258 TOTAL_SEGS(sbi), p.offset); 262 TOTAL_SEGS(sbi), p.offset);
@@ -265,13 +269,11 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
265 break; 269 break;
266 } 270 }
267 p.offset = ((segno / p.ofs_unit) * p.ofs_unit) + p.ofs_unit; 271 p.offset = ((segno / p.ofs_unit) * p.ofs_unit) + p.ofs_unit;
272 secno = GET_SECNO(sbi, segno);
268 273
269 if (test_bit(segno, dirty_i->victim_segmap[FG_GC])) 274 if (sec_usage_check(sbi, secno))
270 continue; 275 continue;
271 if (gc_type == BG_GC && 276 if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
272 test_bit(segno, dirty_i->victim_segmap[BG_GC]))
273 continue;
274 if (IS_CURSEC(sbi, GET_SECNO(sbi, segno)))
275 continue; 277 continue;
276 278
277 cost = get_gc_cost(sbi, segno, &p); 279 cost = get_gc_cost(sbi, segno, &p);
@@ -291,13 +293,14 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
291 } 293 }
292got_it: 294got_it:
293 if (p.min_segno != NULL_SEGNO) { 295 if (p.min_segno != NULL_SEGNO) {
294 *result = (p.min_segno / p.ofs_unit) * p.ofs_unit;
295 if (p.alloc_mode == LFS) { 296 if (p.alloc_mode == LFS) {
296 int i; 297 secno = GET_SECNO(sbi, p.min_segno);
297 for (i = 0; i < p.ofs_unit; i++) 298 if (gc_type == FG_GC)
298 set_bit(*result + i, 299 sbi->cur_victim_sec = secno;
299 dirty_i->victim_segmap[gc_type]); 300 else
301 set_bit(secno, dirty_i->victim_secmap);
300 } 302 }
303 *result = (p.min_segno / p.ofs_unit) * p.ofs_unit;
301 } 304 }
302 mutex_unlock(&dirty_i->seglist_lock); 305 mutex_unlock(&dirty_i->seglist_lock);
303 306
@@ -662,9 +665,11 @@ gc_more:
662 for (i = 0; i < sbi->segs_per_sec; i++) 665 for (i = 0; i < sbi->segs_per_sec; i++)
663 do_garbage_collect(sbi, segno + i, &ilist, gc_type); 666 do_garbage_collect(sbi, segno + i, &ilist, gc_type);
664 667
665 if (gc_type == FG_GC && 668 if (gc_type == FG_GC) {
666 get_valid_blocks(sbi, segno, sbi->segs_per_sec) == 0) 669 sbi->cur_victim_sec = NULL_SEGNO;
667 nfree++; 670 nfree++;
671 WARN_ON(get_valid_blocks(sbi, segno, sbi->segs_per_sec));
672 }
668 673
669 if (has_not_enough_free_secs(sbi, nfree)) 674 if (has_not_enough_free_secs(sbi, nfree))
670 goto gc_more; 675 goto gc_more;