diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 7fd3a181af61..3e69b94e9465 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -4274,7 +4274,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, struct f2fs_gc_control *gc_control); void f2fs_build_gc_manager(struct f2fs_sb_info *sbi); int f2fs_gc_range(struct f2fs_sb_info *sbi, unsigned int start_seg, unsigned int end_seg, - bool dry_run, unsigned int dry_run_sections); + bool dry_run, unsigned int dry_run_sections, bool lock); void f2fs_reset_gc_victim_resource(struct f2fs_sb_info *sbi, unsigned int start, unsigned int end); int f2fs_resize_fs(struct file *filp, __u64 block_count); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 76316e537f65..a54b3ab52f1a 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -3828,7 +3828,7 @@ static int f2fs_ioc_reserve_dev_alias(struct file *filp) } /* do GC to move out valid blocks in the range all at once! */ - err = f2fs_gc_range(sbi, start, end, false, 0); + err = f2fs_gc_range(sbi, start, end, false, 0, false); if (err) { f2fs_unlock_op(sbi, &lc); goto out_gc_unlock; diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 51fc8c69eb25..2f97a7a98517 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -2150,8 +2150,9 @@ void f2fs_build_gc_manager(struct f2fs_sb_info *sbi) int f2fs_gc_range(struct f2fs_sb_info *sbi, unsigned int start_seg, unsigned int end_seg, - bool dry_run, unsigned int dry_run_sections) + bool dry_run, unsigned int dry_run_sections, bool lock) { + struct f2fs_lock_context lc; unsigned int segno; unsigned int gc_secs = dry_run_sections; @@ -2164,28 +2165,43 @@ int f2fs_gc_range(struct f2fs_sb_info *sbi, .ilist = LIST_HEAD_INIT(gc_list.ilist), .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS), }; + int err = 0; + + if (lock) + f2fs_down_write_trace(&sbi->gc_lock, &lc); /* * avoid migrating empty section, as it can be allocated by * log in parallel. */ if (!get_valid_blocks(sbi, segno, true)) - continue; + goto next; if (is_cursec(sbi, GET_SEC_FROM_SEG(sbi, segno))) - continue; + goto next; do_garbage_collect(sbi, segno, &gc_list, FG_GC, true, false); put_gc_inode(&gc_list); - if (!dry_run && get_valid_blocks(sbi, segno, true)) - return -EAGAIN; + if (!dry_run && get_valid_blocks(sbi, segno, true)) { + err = -EAGAIN; + goto next; + } if (dry_run && dry_run_sections && - !get_valid_blocks(sbi, segno, true) && --gc_secs == 0) - break; + !get_valid_blocks(sbi, segno, true)) { + --gc_secs; + goto next; + } if (fatal_signal_pending(current)) - return -ERESTARTSYS; + err = -ERESTARTSYS; +next: + if (lock) + f2fs_up_write_trace(&sbi->gc_lock, &lc); + if (err) + return err; + if (dry_run && dry_run_sections && !gc_secs) + return 0; } return 0; @@ -2231,7 +2247,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi, } /* do GC to move out valid blocks in the range */ - err = f2fs_gc_range(sbi, start, end, dry_run, 0); + err = f2fs_gc_range(sbi, start, end, dry_run, 0, false); if (err || dry_run) goto out; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 7bc779c8e935..caa46c866443 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -3473,10 +3473,8 @@ int f2fs_allocate_pinning_section(struct f2fs_sb_info *sbi) f2fs_unlock_op(sbi, &lc); if (f2fs_sb_has_blkzoned(sbi) && err == -EAGAIN && gc_required) { - f2fs_down_write_trace(&sbi->gc_lock, &lc); err = f2fs_gc_range(sbi, 0, sbi->first_seq_zone_segno - 1, - true, ZONED_PIN_SEC_REQUIRED_COUNT); - f2fs_up_write_trace(&sbi->gc_lock, &lc); + true, ZONED_PIN_SEC_REQUIRED_COUNT, true); if (err) return err; err = f2fs_sync_fs(sbi->sb, 1);