@@ -646,6 +646,54 @@ static void release_victim_entry(struct f2fs_sb_info *sbi)
646646 f2fs_bug_on (sbi , !list_empty (& am -> victim_list ));
647647}
648648
649+ static bool f2fs_pin_section (struct f2fs_sb_info * sbi , unsigned int segno )
650+ {
651+ struct dirty_seglist_info * dirty_i = DIRTY_I (sbi );
652+ unsigned int secno = GET_SEC_FROM_SEG (sbi , segno );
653+
654+ if (!dirty_i -> enable_pin_section )
655+ return false;
656+ if (!test_and_set_bit (secno , dirty_i -> pinned_secmap ))
657+ dirty_i -> pinned_secmap_cnt ++ ;
658+ return true;
659+ }
660+
661+ static bool f2fs_pinned_section_exists (struct dirty_seglist_info * dirty_i )
662+ {
663+ return dirty_i -> pinned_secmap_cnt ;
664+ }
665+
666+ static bool f2fs_section_is_pinned (struct dirty_seglist_info * dirty_i ,
667+ unsigned int secno )
668+ {
669+ return dirty_i -> enable_pin_section &&
670+ f2fs_pinned_section_exists (dirty_i ) &&
671+ test_bit (secno , dirty_i -> pinned_secmap );
672+ }
673+
674+ static void f2fs_unpin_all_sections (struct f2fs_sb_info * sbi , bool enable )
675+ {
676+ unsigned int bitmap_size = f2fs_bitmap_size (MAIN_SECS (sbi ));
677+
678+ if (f2fs_pinned_section_exists (DIRTY_I (sbi ))) {
679+ memset (DIRTY_I (sbi )-> pinned_secmap , 0 , bitmap_size );
680+ DIRTY_I (sbi )-> pinned_secmap_cnt = 0 ;
681+ }
682+ DIRTY_I (sbi )-> enable_pin_section = enable ;
683+ }
684+
685+ static int f2fs_gc_pinned_control (struct inode * inode , int gc_type ,
686+ unsigned int segno )
687+ {
688+ if (!f2fs_is_pinned_file (inode ))
689+ return 0 ;
690+ if (gc_type != FG_GC )
691+ return - EBUSY ;
692+ if (!f2fs_pin_section (F2FS_I_SB (inode ), segno ))
693+ f2fs_pin_file_control (inode , true);
694+ return - EAGAIN ;
695+ }
696+
649697/*
650698 * This function is called from two paths.
651699 * One is garbage collection and the other is SSR segment selection.
@@ -787,6 +835,9 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
787835 if (gc_type == BG_GC && test_bit (secno , dirty_i -> victim_secmap ))
788836 goto next ;
789837
838+ if (gc_type == FG_GC && f2fs_section_is_pinned (dirty_i , secno ))
839+ goto next ;
840+
790841 if (is_atgc ) {
791842 add_victim_entry (sbi , & p , segno );
792843 goto next ;
@@ -1201,12 +1252,9 @@ static int move_data_block(struct inode *inode, block_t bidx,
12011252 goto out ;
12021253 }
12031254
1204- if (f2fs_is_pinned_file (inode )) {
1205- if (gc_type == FG_GC )
1206- f2fs_pin_file_control (inode , true);
1207- err = - EAGAIN ;
1255+ err = f2fs_gc_pinned_control (inode , gc_type , segno );
1256+ if (err )
12081257 goto out ;
1209- }
12101258
12111259 set_new_dnode (& dn , inode , NULL , NULL , 0 );
12121260 err = f2fs_get_dnode_of_data (& dn , bidx , LOOKUP_NODE );
@@ -1351,12 +1399,9 @@ static int move_data_page(struct inode *inode, block_t bidx, int gc_type,
13511399 err = - EAGAIN ;
13521400 goto out ;
13531401 }
1354- if (f2fs_is_pinned_file (inode )) {
1355- if (gc_type == FG_GC )
1356- f2fs_pin_file_control (inode , true);
1357- err = - EAGAIN ;
1402+ err = f2fs_gc_pinned_control (inode , gc_type , segno );
1403+ if (err )
13581404 goto out ;
1359- }
13601405
13611406 if (gc_type == BG_GC ) {
13621407 if (PageWriteback (page )) {
@@ -1476,14 +1521,15 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
14761521 ofs_in_node = le16_to_cpu (entry -> ofs_in_node );
14771522
14781523 if (phase == 3 ) {
1524+ int err ;
1525+
14791526 inode = f2fs_iget (sb , dni .ino );
14801527 if (IS_ERR (inode ) || is_bad_inode (inode ) ||
14811528 special_file (inode -> i_mode ))
14821529 continue ;
14831530
1484- if (is_inode_flag_set (inode , FI_PIN_FILE ) &&
1485- gc_type == FG_GC ) {
1486- f2fs_pin_file_control (inode , true);
1531+ err = f2fs_gc_pinned_control (inode , gc_type , segno );
1532+ if (err == - EAGAIN ) {
14871533 iput (inode );
14881534 return submitted ;
14891535 }
@@ -1766,9 +1812,17 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
17661812 ret = - EINVAL ;
17671813 goto stop ;
17681814 }
1815+ retry :
17691816 ret = __get_victim (sbi , & segno , gc_type );
1770- if (ret )
1817+ if (ret ) {
1818+ /* allow to search victim from sections has pinned data */
1819+ if (ret == - ENODATA && gc_type == FG_GC &&
1820+ f2fs_pinned_section_exists (DIRTY_I (sbi ))) {
1821+ f2fs_unpin_all_sections (sbi , false);
1822+ goto retry ;
1823+ }
17711824 goto stop ;
1825+ }
17721826
17731827 seg_freed = do_garbage_collect (sbi , segno , & gc_list , gc_type , force );
17741828 if (gc_type == FG_GC &&
@@ -1819,6 +1873,9 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
18191873 SIT_I (sbi )-> last_victim [ALLOC_NEXT ] = 0 ;
18201874 SIT_I (sbi )-> last_victim [FLUSH_DEVICE ] = init_segno ;
18211875
1876+ if (gc_type == FG_GC )
1877+ f2fs_unpin_all_sections (sbi , true);
1878+
18221879 trace_f2fs_gc_end (sbi -> sb , ret , total_freed , sec_freed ,
18231880 get_pages (sbi , F2FS_DIRTY_NODES ),
18241881 get_pages (sbi , F2FS_DIRTY_DENTS ),
0 commit comments