Commit 5062b5be authored by Daeho Jeong's avatar Daeho Jeong Committed by Jaegeuk Kim
Browse files

f2fs: make BG GC more aggressive for zoned devices



Since we don't have any GC on device side for zoned devices, need more
aggressive BG GC. So, tune the parameters for that.

Signed-off-by: default avatarDaeho Jeong <daehojeong@google.com>
Reviewed-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 0638a319
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -2879,13 +2879,26 @@ static inline bool is_inflight_io(struct f2fs_sb_info *sbi, int type)
	return false;
}

static inline bool is_inflight_read_io(struct f2fs_sb_info *sbi)
{
	return get_pages(sbi, F2FS_RD_DATA) || get_pages(sbi, F2FS_DIO_READ);
}

static inline bool is_idle(struct f2fs_sb_info *sbi, int type)
{
	bool zoned_gc = (type == GC_TIME &&
			F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_BLKZONED));

	if (sbi->gc_mode == GC_URGENT_HIGH)
		return true;

	if (zoned_gc) {
		if (is_inflight_read_io(sbi))
			return false;
	} else {
		if (is_inflight_io(sbi, type))
			return false;
	}

	if (sbi->gc_mode == GC_URGENT_MID)
		return true;
@@ -2894,6 +2907,9 @@ static inline bool is_idle(struct f2fs_sb_info *sbi, int type)
			(type == DISCARD_TIME || type == GC_TIME))
		return true;

	if (zoned_gc)
		return true;

	return f2fs_time_over(sbi, type);
}

+21 −4
Original line number Diff line number Diff line
@@ -116,7 +116,17 @@ static int gc_thread_func(void *data)
			goto next;
		}

		if (has_enough_invalid_blocks(sbi))
		if (f2fs_sb_has_blkzoned(sbi)) {
			if (has_enough_free_blocks(sbi, LIMIT_NO_ZONED_GC)) {
				wait_ms = gc_th->no_gc_sleep_time;
				f2fs_up_write(&sbi->gc_lock);
				goto next;
			}
			if (wait_ms == gc_th->no_gc_sleep_time)
				wait_ms = gc_th->max_sleep_time;
		}

		if (need_to_boost_gc(sbi))
			decrease_sleep_time(gc_th, &wait_ms);
		else
			increase_sleep_time(gc_th, &wait_ms);
@@ -179,9 +189,16 @@ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi)
		return -ENOMEM;

	gc_th->urgent_sleep_time = DEF_GC_THREAD_URGENT_SLEEP_TIME;

	if (f2fs_sb_has_blkzoned(sbi)) {
		gc_th->min_sleep_time = DEF_GC_THREAD_MIN_SLEEP_TIME_ZONED;
		gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME_ZONED;
		gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME_ZONED;
	} else {
		gc_th->min_sleep_time = DEF_GC_THREAD_MIN_SLEEP_TIME;
		gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME;
		gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME;
	}

	gc_th->gc_wake = false;

+21 −0
Original line number Diff line number Diff line
@@ -15,6 +15,11 @@
#define DEF_GC_THREAD_MAX_SLEEP_TIME	60000
#define DEF_GC_THREAD_NOGC_SLEEP_TIME	300000	/* wait 5 min */

/* GC sleep parameters for zoned deivces */
#define DEF_GC_THREAD_MIN_SLEEP_TIME_ZONED	10
#define DEF_GC_THREAD_MAX_SLEEP_TIME_ZONED	20
#define DEF_GC_THREAD_NOGC_SLEEP_TIME_ZONED	60000

/* choose candidates from sections which has age of more than 7 days */
#define DEF_GC_THREAD_AGE_THRESHOLD		(60 * 60 * 24 * 7)
#define DEF_GC_THREAD_CANDIDATE_RATIO		20	/* select 20% oldest sections as candidates */
@@ -25,6 +30,9 @@
#define LIMIT_INVALID_BLOCK	40 /* percentage over total user space */
#define LIMIT_FREE_BLOCK	40 /* percentage over invalid + free space */

#define LIMIT_NO_ZONED_GC	60 /* percentage over total user space of no gc for zoned devices */
#define LIMIT_BOOST_ZONED_GC	25 /* percentage over total user space of boosted gc for zoned devices */

#define DEF_GC_FAILED_PINNED_FILES	2048
#define MAX_GC_FAILED_PINNED_FILES	USHRT_MAX

@@ -152,6 +160,12 @@ static inline void decrease_sleep_time(struct f2fs_gc_kthread *gc_th,
		*wait -= min_time;
}

static inline bool has_enough_free_blocks(struct f2fs_sb_info *sbi,
						unsigned int limit_perc)
{
	return free_sections(sbi) > ((sbi->total_sections * limit_perc) / 100);
}

static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
{
	block_t user_block_count = sbi->user_block_count;
@@ -167,3 +181,10 @@ static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
		free_user_blocks(sbi) <
			limit_free_user_blocks(invalid_user_blocks));
}

static inline bool need_to_boost_gc(struct f2fs_sb_info *sbi)
{
	if (f2fs_sb_has_blkzoned(sbi))
		return !has_enough_free_blocks(sbi, LIMIT_BOOST_ZONED_GC);
	return has_enough_invalid_blocks(sbi);
}
+5 −0
Original line number Diff line number Diff line
@@ -706,6 +706,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
			if (!strcmp(name, "on")) {
				F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON;
			} else if (!strcmp(name, "off")) {
				if (f2fs_sb_has_blkzoned(sbi)) {
					f2fs_warn(sbi, "zoned devices need bggc");
					kfree(name);
					return -EINVAL;
				}
				F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_OFF;
			} else if (!strcmp(name, "sync")) {
				F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_SYNC;