diff options
Diffstat (limited to 'fs/f2fs/gc.c')
-rw-r--r-- | fs/f2fs/gc.c | 43 |
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, | |||
160 | static unsigned int check_bg_victims(struct f2fs_sb_info *sbi) | 160 | static 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], | 171 | next: |
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 | } |
292 | got_it: | 294 | got_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; |