On 2020/6/24 17:40, Qilong Zhang wrote: > When f2fs_ioc_gc_range performs multiple segments gc ops, the return > value of f2fs_ioc_gc_range is determined by the last segment gc ops. > If its ops failed, the f2fs_ioc_gc_range will be considered to be failed > despite some of previous segments gc ops succeeded. Therefore, so we > fix: Redefine the return value of getting victim ops and add exception > handle for f2fs_gc. In particular, 1).if target has no valid block, it > will go on. 2).if target sectoion has valid block(s), but it is current > section, we will reminder the caller. > > Signed-off-by: Qilong Zhang <zhangqilo...@huawei.com> > --- > fs/f2fs/file.c | 5 +++++ > fs/f2fs/gc.c | 19 +++++++++++++------ > fs/f2fs/segment.c | 4 ++-- > 3 files changed, 20 insertions(+), 8 deletions(-) > > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c > index 3268f8dd59bb..209dd9cb4b7b 100644 > --- a/fs/f2fs/file.c > +++ b/fs/f2fs/file.c > @@ -2527,6 +2527,11 @@ static int f2fs_ioc_gc_range(struct file *filp, > unsigned long arg) > } > > ret = f2fs_gc(sbi, range.sync, true, GET_SEGNO(sbi, range.start)); > + if (ret) { > + if (ret == -EAGAIN) > + ret = -EBUSY; > + goto out; > + } > range.start += BLKS_PER_SEC(sbi); > if (range.start <= end) > goto do_more; > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c > index 5b95d5a146eb..297e53ef4cb1 100644 > --- a/fs/f2fs/gc.c > +++ b/fs/f2fs/gc.c > @@ -321,6 +321,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, > unsigned int secno, last_victim; > unsigned int last_segment; > unsigned int nsearched = 0; > + int ret; > > mutex_lock(&dirty_i->seglist_lock); > last_segment = MAIN_SECS(sbi) * sbi->segs_per_sec; > @@ -332,12 +333,18 @@ static int get_victim_by_default(struct f2fs_sb_info > *sbi, > p.min_cost = get_max_cost(sbi, &p); > > if (*result != NULL_SEGNO) { > - if (get_valid_blocks(sbi, *result, false) && > - !sec_usage_check(sbi, GET_SEC_FROM_SEG(sbi, *result))) > + ret = 0; > + if (!get_valid_blocks(sbi, *result, false)) > + goto out; > + > + if (sec_usage_check(sbi, GET_SEC_FROM_SEG(sbi, *result))) > + ret = -EAGAIN;
Look at this again, it looks EBUSY will be more precise here? how about changing to return EBUSY? #define EBUSY 16 /* Device or resource busy */ #define EAGAIN 11 /* Try again */ Otherwise it looks good to me, since it's nitpick, so feel free to add: Reviewed-by: Chao Yu <yuch...@huawei.com> Thanks, > + else > p.min_segno = *result; > goto out; > } > > + ret = -ENODATA; > if (p.max_search == 0) > goto out; > > @@ -440,6 +447,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, > else > set_bit(secno, dirty_i->victim_secmap); > } > + ret = 0; > > } > out: > @@ -449,7 +457,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, > prefree_segments(sbi), free_segments(sbi)); > mutex_unlock(&dirty_i->seglist_lock); > > - return (p.min_segno == NULL_SEGNO) ? 0 : 1; > + return ret; > } > > static const struct victim_selection default_v_ops = { > @@ -1333,10 +1341,9 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, > ret = -EINVAL; > goto stop; > } > - if (!__get_victim(sbi, &segno, gc_type)) { > - ret = -ENODATA; > + ret = __get_victim(sbi, &segno, gc_type); > + if (ret) > goto stop; > - } > > seg_freed = do_garbage_collect(sbi, segno, &gc_list, gc_type); > if (gc_type == FG_GC && seg_freed == sbi->segs_per_sec) > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c > index 196f31503511..b9fd93761b0a 100644 > --- a/fs/f2fs/segment.c > +++ b/fs/f2fs/segment.c > @@ -2605,7 +2605,7 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, > int type) > bool reversed = false; > > /* f2fs_need_SSR() already forces to do this */ > - if (v_ops->get_victim(sbi, &segno, BG_GC, type, SSR)) { > + if (!v_ops->get_victim(sbi, &segno, BG_GC, type, SSR)) { > curseg->next_segno = segno; > return 1; > } > @@ -2632,7 +2632,7 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, > int type) > for (; cnt-- > 0; reversed ? i-- : i++) { > if (i == type) > continue; > - if (v_ops->get_victim(sbi, &segno, BG_GC, i, SSR)) { > + if (!v_ops->get_victim(sbi, &segno, BG_GC, i, SSR)) { > curseg->next_segno = segno; > return 1; > } > _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel