@@ -35,6 +35,9 @@ static int gc_thread_func(void *data)
3535 wait_queue_head_t * wq = & sbi -> gc_thread -> gc_wait_queue_head ;
3636 wait_queue_head_t * fggc_wq = & sbi -> gc_thread -> fggc_wq ;
3737 unsigned int wait_ms ;
38+ struct f2fs_gc_control gc_control = {
39+ .victim_segno = NULL_SEGNO ,
40+ .should_migrate_blocks = false };
3841
3942 wait_ms = gc_th -> min_sleep_time ;
4043
@@ -141,8 +144,12 @@ static int gc_thread_func(void *data)
141144 if (foreground )
142145 sync_mode = false;
143146
147+ gc_control .init_gc_type = sync_mode ? FG_GC : BG_GC ;
148+ gc_control .no_bg_gc = foreground ;
149+ gc_control .err_gc_skipped = sync_mode ;
150+
144151 /* if return value is not zero, no victim was selected */
145- if (f2fs_gc (sbi , sync_mode , ! foreground , false, NULL_SEGNO ))
152+ if (f2fs_gc (sbi , & gc_control ))
146153 wait_ms = gc_th -> no_gc_sleep_time ;
147154
148155 if (foreground )
@@ -1740,21 +1747,20 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
17401747 return seg_freed ;
17411748}
17421749
1743- int f2fs_gc (struct f2fs_sb_info * sbi , bool sync ,
1744- bool background , bool force , unsigned int segno )
1750+ int f2fs_gc (struct f2fs_sb_info * sbi , struct f2fs_gc_control * gc_control )
17451751{
1746- int gc_type = sync ? FG_GC : BG_GC ;
1752+ int gc_type = gc_control -> init_gc_type ;
1753+ unsigned int segno = gc_control -> victim_segno ;
17471754 int sec_freed = 0 , seg_freed = 0 , total_freed = 0 ;
17481755 int ret = 0 ;
17491756 struct cp_control cpc ;
1750- unsigned int init_segno = segno ;
17511757 struct gc_inode_list gc_list = {
17521758 .ilist = LIST_HEAD_INIT (gc_list .ilist ),
17531759 .iroot = RADIX_TREE_INIT (gc_list .iroot , GFP_NOFS ),
17541760 };
17551761 unsigned int skipped_round = 0 , round = 0 ;
17561762
1757- trace_f2fs_gc_begin (sbi -> sb , sync , background ,
1763+ trace_f2fs_gc_begin (sbi -> sb , gc_type , gc_control -> no_bg_gc ,
17581764 get_pages (sbi , F2FS_DIRTY_NODES ),
17591765 get_pages (sbi , F2FS_DIRTY_DENTS ),
17601766 get_pages (sbi , F2FS_DIRTY_IMETA ),
@@ -1781,8 +1787,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
17811787 * threshold, we can make them free by checkpoint. Then, we
17821788 * secure free segments which doesn't need fggc any more.
17831789 */
1784- if (prefree_segments (sbi ) &&
1785- !is_sbi_flag_set (sbi , SBI_CP_DISABLED )) {
1790+ if (prefree_segments (sbi )) {
17861791 ret = f2fs_write_checkpoint (sbi , & cpc );
17871792 if (ret )
17881793 goto stop ;
@@ -1792,7 +1797,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
17921797 }
17931798
17941799 /* f2fs_balance_fs doesn't need to do BG_GC in critical path. */
1795- if (gc_type == BG_GC && ! background ) {
1800+ if (gc_type == BG_GC && gc_control -> no_bg_gc ) {
17961801 ret = - EINVAL ;
17971802 goto stop ;
17981803 }
@@ -1808,45 +1813,48 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
18081813 goto stop ;
18091814 }
18101815
1811- seg_freed = do_garbage_collect (sbi , segno , & gc_list , gc_type , force );
1812- if (gc_type == FG_GC &&
1813- seg_freed == f2fs_usable_segs_in_sec (sbi , segno ))
1814- sec_freed ++ ;
1816+ seg_freed = do_garbage_collect (sbi , segno , & gc_list , gc_type ,
1817+ gc_control -> should_migrate_blocks );
18151818 total_freed += seg_freed ;
18161819
1817- if (gc_type == FG_GC ) {
1818- if (sbi -> skipped_gc_rwsem )
1819- skipped_round ++ ;
1820- round ++ ;
1821- }
1820+ if (seg_freed == f2fs_usable_segs_in_sec (sbi , segno ))
1821+ sec_freed ++ ;
18221822
18231823 if (gc_type == FG_GC )
18241824 sbi -> cur_victim_sec = NULL_SEGNO ;
18251825
1826- if (sync )
1826+ if (gc_control -> init_gc_type == FG_GC )
18271827 goto stop ;
18281828
1829- if (!has_not_enough_free_secs (sbi , sec_freed , 0 ))
1829+ if (!has_not_enough_free_secs (sbi ,
1830+ (gc_type == FG_GC ) ? sec_freed : 0 , 0 ))
18301831 goto stop ;
18311832
1832- if (skipped_round <= MAX_SKIP_GC_COUNT || skipped_round * 2 < round ) {
1833-
1834- /* Write checkpoint to reclaim prefree segments */
1835- if (free_sections (sbi ) < NR_CURSEG_PERSIST_TYPE &&
1836- prefree_segments (sbi ) &&
1837- !is_sbi_flag_set (sbi , SBI_CP_DISABLED )) {
1833+ /* FG_GC stops GC by skip_count */
1834+ if (gc_type == FG_GC ) {
1835+ if (sbi -> skipped_gc_rwsem )
1836+ skipped_round ++ ;
1837+ round ++ ;
1838+ if (skipped_round > MAX_SKIP_GC_COUNT &&
1839+ skipped_round * 2 >= round ) {
18381840 ret = f2fs_write_checkpoint (sbi , & cpc );
1839- if (ret )
1840- goto stop ;
1841+ goto stop ;
18411842 }
1842- segno = NULL_SEGNO ;
1843- goto gc_more ;
18441843 }
1845- if (gc_type == FG_GC && !is_sbi_flag_set (sbi , SBI_CP_DISABLED ))
1844+
1845+ /* Write checkpoint to reclaim prefree segments */
1846+ if (free_sections (sbi ) < NR_CURSEG_PERSIST_TYPE &&
1847+ prefree_segments (sbi )) {
18461848 ret = f2fs_write_checkpoint (sbi , & cpc );
1849+ if (ret )
1850+ goto stop ;
1851+ }
1852+ segno = NULL_SEGNO ;
1853+ goto gc_more ;
1854+
18471855stop :
18481856 SIT_I (sbi )-> last_victim [ALLOC_NEXT ] = 0 ;
1849- SIT_I (sbi )-> last_victim [FLUSH_DEVICE ] = init_segno ;
1857+ SIT_I (sbi )-> last_victim [FLUSH_DEVICE ] = gc_control -> victim_segno ;
18501858
18511859 if (gc_type == FG_GC )
18521860 f2fs_unpin_all_sections (sbi , true);
@@ -1864,7 +1872,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
18641872
18651873 put_gc_inode (& gc_list );
18661874
1867- if (sync && !ret )
1875+ if (gc_control -> err_gc_skipped && !ret )
18681876 ret = sec_freed ? 0 : - EAGAIN ;
18691877 return ret ;
18701878}
0 commit comments