hi jeageuk, chao How about changing the large section gc in this direction? Thanks
> Change the large section GC to locate valid block segments instead of > performing a sequential search. This modification enhances performance > by reducing unnecessary block scanning in large storage sections. > > example : > [invalid seg 0] [invalid seg 1] [invalid seg 2] > [ valid seg 3] [ valid seg 4] [ valid seg 5] > > Current: In the first GC, nothing is moved, > but in the second GC, segments 3, 4, and 5 are moved. > Change: In the first GC, segments 3, 4, and 5 are moved. > > Signed-off-by: yohan.joung <yohan.jo...@sk.com> > --- > fs/f2fs/f2fs.h | 2 ++ > fs/f2fs/gc.c | 92 +++++++++++++++++++++++++++++++++++-------------- > fs/f2fs/gc.h | 6 ++++ > fs/f2fs/super.c | 8 ++++- > 4 files changed, 82 insertions(+), 26 deletions(-) > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > index f1576dc6ec67..348417edac25 100644 > --- a/fs/f2fs/f2fs.h > +++ b/fs/f2fs/f2fs.h > @@ -4008,6 +4008,8 @@ int f2fs_gc_range(struct f2fs_sb_info *sbi, > int f2fs_resize_fs(struct file *filp, __u64 block_count); > int __init f2fs_create_garbage_collection_cache(void); > void f2fs_destroy_garbage_collection_cache(void); > +int __init f2fs_init_garbage_collection_summary_cache(void); > +void f2fs_destroy_garbage_collection_summary_cache(void); > /* victim selection function for cleaning and SSR */ > int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result, > int gc_type, int type, char alloc_mode, > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c > index 2b8f9239bede..3b63e85fa038 100644 > --- a/fs/f2fs/gc.c > +++ b/fs/f2fs/gc.c > @@ -24,6 +24,7 @@ > #include <trace/events/f2fs.h> > > static struct kmem_cache *victim_entry_slab; > +static struct kmem_cache *gc_page_entry_slab; > > static unsigned int count_bits(const unsigned long *addr, > unsigned int offset, unsigned int len); > @@ -711,6 +712,30 @@ static void release_victim_entry(struct f2fs_sb_info > *sbi) > f2fs_bug_on(sbi, !list_empty(&am->victim_list)); > } > > +static struct gc_page_entry *add_gc_page_entry(struct list_head > *gc_page_list, > + struct page *sum_page, unsigned int > segno) > +{ > + struct gc_page_entry *gpe; > + > + gpe = f2fs_kmem_cache_alloc(gc_page_entry_slab, GFP_NOFS, true, NULL); > + gpe->segno = segno; > + gpe->sum_page = sum_page; > + list_add_tail(&gpe->list, gc_page_list); > + return gpe; > +} > + > +static void release_gc_page_entry(struct list_head *gc_page_list, bool > putpage) > +{ > + struct gc_page_entry *gpe, *tmp; > + > + list_for_each_entry_safe(gpe, tmp, gc_page_list, list) { > + if (putpage) > + f2fs_put_page(gpe->sum_page, 0); > + list_del(&gpe->list); > + kmem_cache_free(gc_page_entry_slab, gpe); > + } > +} > + > static bool f2fs_pin_section(struct f2fs_sb_info *sbi, unsigned int segno) > { > struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); > @@ -1721,14 +1746,18 @@ static int do_garbage_collect(struct f2fs_sb_info > *sbi, > struct page *sum_page; > struct f2fs_summary_block *sum; > struct blk_plug plug; > + struct gc_page_entry *gpe; > unsigned int segno = start_segno; > unsigned int end_segno = start_segno + SEGS_PER_SEC(sbi); > unsigned int sec_end_segno; > + unsigned int window_granularity = 1; > int seg_freed = 0, migrated = 0; > unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ? > SUM_TYPE_DATA : SUM_TYPE_NODE; > unsigned char data_type = (type == SUM_TYPE_DATA) ? DATA : NODE; > int submitted = 0; > + int gc_list_count = 0; > + LIST_HEAD(gc_page_list); > > if (__is_large_section(sbi)) { > sec_end_segno = rounddown(end_segno, SEGS_PER_SEC(sbi)); > @@ -1744,7 +1773,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, > f2fs_usable_segs_in_sec(sbi); > > if (gc_type == BG_GC || one_time) { > - unsigned int window_granularity = > + window_granularity = > sbi->migration_window_granularity; > > if (f2fs_sb_has_blkzoned(sbi) && > @@ -1752,8 +1781,6 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, > sbi->gc_thread->boost_zoned_gc_percent)) > window_granularity *= > BOOST_GC_MULTIPLE; > - > - end_segno = start_segno + window_granularity; > } > > if (end_segno > sec_end_segno) > @@ -1762,37 +1789,38 @@ static int do_garbage_collect(struct f2fs_sb_info > *sbi, > > sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type); > > - /* readahead multi ssa blocks those have contiguous address */ > - if (__is_large_section(sbi)) > + for (segno = start_segno; segno < end_segno; segno++) { > + if (!get_valid_blocks(sbi, segno, false)) > + continue; > + > + /* readahead multi ssa blocks those have contiguous address */ > f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno), > - end_segno - segno, META_SSA, true); > + window_granularity, META_SSA, true); > > - /* reference all summary page */ > - while (segno < end_segno) { > - sum_page = f2fs_get_sum_page(sbi, segno++); > + /* reference all summary page */ > + sum_page = f2fs_get_sum_page(sbi, segno); > if (IS_ERR(sum_page)) { > int err = PTR_ERR(sum_page); > - > - end_segno = segno - 1; > - for (segno = start_segno; segno < end_segno; segno++) { > - sum_page = find_get_page(META_MAPPING(sbi), > - GET_SUM_BLOCK(sbi, segno)); > - f2fs_put_page(sum_page, 0); > - f2fs_put_page(sum_page, 0); > - } > + release_gc_page_entry(&gc_page_list, true); > return err; > } > + add_gc_page_entry(&gc_page_list, sum_page, segno); > unlock_page(sum_page); > + if (++gc_list_count >= window_granularity) > + break; > } > > blk_start_plug(&plug); > > - for (segno = start_segno; segno < end_segno; segno++) { > + list_for_each_entry(gpe, &gc_page_list, list) { > > /* find segment summary of victim */ > - sum_page = find_get_page(META_MAPPING(sbi), > - GET_SUM_BLOCK(sbi, segno)); > - f2fs_put_page(sum_page, 0); > + sum_page = gpe->sum_page; > + segno = gpe->segno; > + if (!sum_page) { > + f2fs_err(sbi, "Failed to get summary page for segment > %u", segno); > + goto skip; > + } > > if (get_valid_blocks(sbi, segno, false) == 0) > goto freed; > @@ -1835,18 +1863,20 @@ static int do_garbage_collect(struct f2fs_sb_info > *sbi, > get_valid_blocks(sbi, segno, false) == 0) > seg_freed++; > > - if (__is_large_section(sbi)) > - sbi->next_victim_seg[gc_type] = > - (segno + 1 < sec_end_segno) ? > - segno + 1 : NULL_SEGNO; > skip: > f2fs_put_page(sum_page, 0); > } > > + if (__is_large_section(sbi) && !list_empty(&gc_page_list)) > + sbi->next_victim_seg[gc_type] = > + (segno + 1 < sec_end_segno) ? > + segno + 1 : NULL_SEGNO; > + > if (submitted) > f2fs_submit_merged_write(sbi, data_type); > > blk_finish_plug(&plug); > + release_gc_page_entry(&gc_page_list, false); > > if (migrated) > stat_inc_gc_sec_count(sbi, data_type, gc_type); > @@ -2008,6 +2038,18 @@ int f2fs_gc(struct f2fs_sb_info *sbi, struct > f2fs_gc_control *gc_control) > return ret; > } > > +int __init f2fs_init_garbage_collection_summary_cache(void) > +{ > + gc_page_entry_slab = f2fs_kmem_cache_create("f2fs_gc_page_entry", > + sizeof(struct gc_page_entry)); > + return gc_page_entry_slab ? 0 : -ENOMEM; > +} > + > +void f2fs_destroy_garbage_collection_summary_cache(void) > +{ > + kmem_cache_destroy(gc_page_entry_slab); > +} > + > int __init f2fs_create_garbage_collection_cache(void) > { > victim_entry_slab = f2fs_kmem_cache_create("f2fs_victim_entry", > diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h > index 5c1eaf55e127..9c8695efe394 100644 > --- a/fs/f2fs/gc.h > +++ b/fs/f2fs/gc.h > @@ -82,6 +82,12 @@ struct victim_entry { > struct list_head list; > }; > > +struct gc_page_entry { > + unsigned int segno; > + struct page *sum_page; > + struct list_head list; > +}; > + > /* > * inline functions > */ > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c > index f087b2b71c89..a3241730fe4f 100644 > --- a/fs/f2fs/super.c > +++ b/fs/f2fs/super.c > @@ -5090,9 +5090,12 @@ static int __init init_f2fs_fs(void) > err = f2fs_create_garbage_collection_cache(); > if (err) > goto free_extent_cache; > - err = f2fs_init_sysfs(); > + err = f2fs_init_garbage_collection_summary_cache(); > if (err) > goto free_garbage_collection_cache; > + err = f2fs_init_sysfs(); > + if (err) > + goto free_garbage_collection_summary_cache; > err = f2fs_init_shrinker(); > if (err) > goto free_sysfs; > @@ -5141,6 +5144,8 @@ static int __init init_f2fs_fs(void) > f2fs_exit_shrinker(); > free_sysfs: > f2fs_exit_sysfs(); > +free_garbage_collection_summary_cache: > + f2fs_destroy_garbage_collection_summary_cache(); > free_garbage_collection_cache: > f2fs_destroy_garbage_collection_cache(); > free_extent_cache: > @@ -5172,6 +5177,7 @@ static void __exit exit_f2fs_fs(void) > f2fs_destroy_root_stats(); > f2fs_exit_shrinker(); > f2fs_exit_sysfs(); > + f2fs_destroy_garbage_collection_summary_cache(); > f2fs_destroy_garbage_collection_cache(); > f2fs_destroy_extent_cache(); > f2fs_destroy_recovery_cache(); > -- > 2.33.0 > > > > _______________________________________________ > Linux-f2fs-devel mailing list > Linux-f2fs-devel@lists.sourceforge.net _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel