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

Reply via email to