Skip to content

Commit e3080b0

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: support subsectional garbage collection
Section is minimal garbage collection unit of f2fs, in zoned block device, or ancient block mapping flash device, in order to improve GC efficiency, we can align GC unit to lower device erase unit, normally, it consists of multiple of segments. Once background or foreground GC triggers, it brings a large number of IOs, which will impact user IO, and also occupy cpu/memory resource intensively. So, to reduce impact of GC on large size section, this patch supports subsectional GC, in one cycle of GC, it only migrate partial segment{s} in victim section. Currently, by default, we use sbi->segs_per_sec as migration granularity. Signed-off-by: Chao Yu <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent 2c70c5e commit e3080b0

File tree

3 files changed

+39
-6
lines changed

3 files changed

+39
-6
lines changed

fs/f2fs/f2fs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,7 @@ struct f2fs_sb_info {
12631263
struct f2fs_gc_kthread *gc_thread; /* GC thread */
12641264
unsigned int cur_victim_sec; /* current victim section num */
12651265
unsigned int gc_mode; /* current GC state */
1266+
unsigned int next_victim_seg[2]; /* next segment in victim section */
12661267
/* for skip statistic */
12671268
unsigned long long skipped_atomic_files[2]; /* FG_GC and BG_GC */
12681269
unsigned long long skipped_gc_rwsem; /* FG_GC only */
@@ -1272,6 +1273,8 @@ struct f2fs_sb_info {
12721273

12731274
/* maximum # of trials to find a victim segment for SSR and GC */
12741275
unsigned int max_victim_search;
1276+
/* migration granularity of garbage collection, unit: segment */
1277+
unsigned int migration_granularity;
12751278

12761279
/*
12771280
* for stat information.

fs/f2fs/gc.c

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,22 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
333333
if (p.max_search == 0)
334334
goto out;
335335

336+
if (__is_large_section(sbi) && p.alloc_mode == LFS) {
337+
if (sbi->next_victim_seg[BG_GC] != NULL_SEGNO) {
338+
p.min_segno = sbi->next_victim_seg[BG_GC];
339+
*result = p.min_segno;
340+
sbi->next_victim_seg[BG_GC] = NULL_SEGNO;
341+
goto got_result;
342+
}
343+
if (gc_type == FG_GC &&
344+
sbi->next_victim_seg[FG_GC] != NULL_SEGNO) {
345+
p.min_segno = sbi->next_victim_seg[FG_GC];
346+
*result = p.min_segno;
347+
sbi->next_victim_seg[FG_GC] = NULL_SEGNO;
348+
goto got_result;
349+
}
350+
}
351+
336352
last_victim = sm->last_victim[p.gc_mode];
337353
if (p.alloc_mode == LFS && gc_type == FG_GC) {
338354
p.min_segno = check_bg_victims(sbi);
@@ -395,14 +411,15 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
395411
}
396412
if (p.min_segno != NULL_SEGNO) {
397413
got_it:
414+
*result = (p.min_segno / p.ofs_unit) * p.ofs_unit;
415+
got_result:
398416
if (p.alloc_mode == LFS) {
399417
secno = GET_SEC_FROM_SEG(sbi, p.min_segno);
400418
if (gc_type == FG_GC)
401419
sbi->cur_victim_sec = secno;
402420
else
403421
set_bit(secno, dirty_i->victim_secmap);
404422
}
405-
*result = (p.min_segno / p.ofs_unit) * p.ofs_unit;
406423

407424
trace_f2fs_get_victim(sbi->sb, type, gc_type, &p,
408425
sbi->cur_victim_sec,
@@ -1103,15 +1120,18 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
11031120
struct blk_plug plug;
11041121
unsigned int segno = start_segno;
11051122
unsigned int end_segno = start_segno + sbi->segs_per_sec;
1106-
int seg_freed = 0;
1123+
int seg_freed = 0, migrated = 0;
11071124
unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ?
11081125
SUM_TYPE_DATA : SUM_TYPE_NODE;
11091126
int submitted = 0;
11101127

1128+
if (__is_large_section(sbi))
1129+
end_segno = rounddown(end_segno, sbi->segs_per_sec);
1130+
11111131
/* readahead multi ssa blocks those have contiguous address */
11121132
if (__is_large_section(sbi))
11131133
f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
1114-
sbi->segs_per_sec, META_SSA, true);
1134+
end_segno - segno, META_SSA, true);
11151135

11161136
/* reference all summary page */
11171137
while (segno < end_segno) {
@@ -1142,16 +1162,19 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
11421162

11431163
if (get_valid_blocks(sbi, segno, false) == 0)
11441164
goto freed;
1165+
if (__is_large_section(sbi) &&
1166+
migrated >= sbi->migration_granularity)
1167+
goto skip;
11451168
if (!PageUptodate(sum_page) || unlikely(f2fs_cp_error(sbi)))
1146-
goto next;
1169+
goto skip;
11471170

11481171
sum = page_address(sum_page);
11491172
if (type != GET_SUM_TYPE((&sum->footer))) {
11501173
f2fs_msg(sbi->sb, KERN_ERR, "Inconsistent segment (%u) "
11511174
"type [%d, %d] in SSA and SIT",
11521175
segno, type, GET_SUM_TYPE((&sum->footer)));
11531176
set_sbi_flag(sbi, SBI_NEED_FSCK);
1154-
goto next;
1177+
goto skip;
11551178
}
11561179

11571180
/*
@@ -1174,7 +1197,11 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
11741197
if (gc_type == FG_GC &&
11751198
get_valid_blocks(sbi, segno, false) == 0)
11761199
seg_freed++;
1177-
next:
1200+
migrated++;
1201+
1202+
if (__is_large_section(sbi) && segno + 1 < end_segno)
1203+
sbi->next_victim_seg[gc_type] = segno + 1;
1204+
skip:
11781205
f2fs_put_page(sum_page, 0);
11791206
}
11801207

fs/f2fs/super.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2692,7 +2692,10 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
26922692
sbi->node_ino_num = le32_to_cpu(raw_super->node_ino);
26932693
sbi->meta_ino_num = le32_to_cpu(raw_super->meta_ino);
26942694
sbi->cur_victim_sec = NULL_SECNO;
2695+
sbi->next_victim_seg[BG_GC] = NULL_SEGNO;
2696+
sbi->next_victim_seg[FG_GC] = NULL_SEGNO;
26952697
sbi->max_victim_search = DEF_MAX_VICTIM_SEARCH;
2698+
sbi->migration_granularity = sbi->segs_per_sec;
26962699

26972700
sbi->dir_level = DEF_DIR_LEVEL;
26982701
sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL;

0 commit comments

Comments
 (0)