Commit 97767500 authored by Qilong Zhang's avatar Qilong Zhang Committed by Jaegeuk Kim
Browse files

f2fs: add f2fs_gc exception handle in f2fs_ioc_gc_range



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: default avatarQilong Zhang <zhangqilong3@huawei.com>
Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent f608c38c
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -2525,6 +2525,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 == -EBUSY)
			ret = -EAGAIN;
		goto out;
	}
	range.start += BLKS_PER_SEC(sbi);
	if (range.start <= end)
		goto do_more;
+14 −6
Original line number Diff line number Diff line
@@ -330,6 +330,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 = 0;

	mutex_lock(&dirty_i->seglist_lock);
	last_segment = MAIN_SECS(sbi) * sbi->segs_per_sec;
@@ -341,12 +342,19 @@ 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)))
		if (!get_valid_blocks(sbi, *result, false)) {
			ret = -ENODATA;
			goto out;
		}

		if (sec_usage_check(sbi, GET_SEC_FROM_SEG(sbi, *result)))
			ret = -EBUSY;
		else
			p.min_segno = *result;
		goto out;
	}

	ret = -ENODATA;
	if (p.max_search == 0)
		goto out;

@@ -447,6 +455,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
			else
				set_bit(secno, dirty_i->victim_secmap);
		}
		ret = 0;

	}
out:
@@ -456,7 +465,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 = {
@@ -1340,10 +1349,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)
+2 −2
Original line number Diff line number Diff line
@@ -2631,7 +2631,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;
	}
@@ -2658,7 +2658,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;
		}