162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * fs/f2fs/gc.h
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd.
662306a36Sopenharmony_ci *             http://www.samsung.com/
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#define GC_THREAD_MIN_WB_PAGES		1	/*
962306a36Sopenharmony_ci						 * a threshold to determine
1062306a36Sopenharmony_ci						 * whether IO subsystem is idle
1162306a36Sopenharmony_ci						 * or not
1262306a36Sopenharmony_ci						 */
1362306a36Sopenharmony_ci#define DEF_GC_THREAD_URGENT_SLEEP_TIME	500	/* 500 ms */
1462306a36Sopenharmony_ci#define DEF_GC_THREAD_MIN_SLEEP_TIME	30000	/* milliseconds */
1562306a36Sopenharmony_ci#define DEF_GC_THREAD_MAX_SLEEP_TIME	60000
1662306a36Sopenharmony_ci#define DEF_GC_THREAD_NOGC_SLEEP_TIME	300000	/* wait 5 min */
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* choose candidates from sections which has age of more than 7 days */
1962306a36Sopenharmony_ci#define DEF_GC_THREAD_AGE_THRESHOLD		(60 * 60 * 24 * 7)
2062306a36Sopenharmony_ci#define DEF_GC_THREAD_CANDIDATE_RATIO		20	/* select 20% oldest sections as candidates */
2162306a36Sopenharmony_ci#define DEF_GC_THREAD_MAX_CANDIDATE_COUNT	10	/* select at most 10 sections as candidates */
2262306a36Sopenharmony_ci#define DEF_GC_THREAD_AGE_WEIGHT		60	/* age weight */
2362306a36Sopenharmony_ci#define DEFAULT_ACCURACY_CLASS			10000	/* accuracy class */
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define LIMIT_INVALID_BLOCK	40 /* percentage over total user space */
2662306a36Sopenharmony_ci#define LIMIT_FREE_BLOCK	40 /* percentage over invalid + free space */
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define DEF_GC_FAILED_PINNED_FILES	2048
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* Search max. number of dirty segments to select a victim segment */
3162306a36Sopenharmony_ci#define DEF_MAX_VICTIM_SEARCH 4096 /* covers 8GB */
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define NR_GC_CHECKPOINT_SECS (3)	/* data/node/dentry sections */
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistruct f2fs_gc_kthread {
3662306a36Sopenharmony_ci	struct task_struct *f2fs_gc_task;
3762306a36Sopenharmony_ci	wait_queue_head_t gc_wait_queue_head;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	/* for gc sleep time */
4062306a36Sopenharmony_ci	unsigned int urgent_sleep_time;
4162306a36Sopenharmony_ci	unsigned int min_sleep_time;
4262306a36Sopenharmony_ci	unsigned int max_sleep_time;
4362306a36Sopenharmony_ci	unsigned int no_gc_sleep_time;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	/* for changing gc mode */
4662306a36Sopenharmony_ci	bool gc_wake;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	/* for GC_MERGE mount option */
4962306a36Sopenharmony_ci	wait_queue_head_t fggc_wq;		/*
5062306a36Sopenharmony_ci						 * caller of f2fs_balance_fs()
5162306a36Sopenharmony_ci						 * will wait on this wait queue.
5262306a36Sopenharmony_ci						 */
5362306a36Sopenharmony_ci};
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistruct gc_inode_list {
5662306a36Sopenharmony_ci	struct list_head ilist;
5762306a36Sopenharmony_ci	struct radix_tree_root iroot;
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistruct victim_entry {
6162306a36Sopenharmony_ci	struct rb_node rb_node;		/* rb node located in rb-tree */
6262306a36Sopenharmony_ci	unsigned long long mtime;	/* mtime of section */
6362306a36Sopenharmony_ci	unsigned int segno;		/* segment No. */
6462306a36Sopenharmony_ci	struct list_head list;
6562306a36Sopenharmony_ci};
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci/*
6862306a36Sopenharmony_ci * inline functions
6962306a36Sopenharmony_ci */
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/*
7262306a36Sopenharmony_ci * On a Zoned device zone-capacity can be less than zone-size and if
7362306a36Sopenharmony_ci * zone-capacity is not aligned to f2fs segment size(2MB), then the segment
7462306a36Sopenharmony_ci * starting just before zone-capacity has some blocks spanning across the
7562306a36Sopenharmony_ci * zone-capacity, these blocks are not usable.
7662306a36Sopenharmony_ci * Such spanning segments can be in free list so calculate the sum of usable
7762306a36Sopenharmony_ci * blocks in currently free segments including normal and spanning segments.
7862306a36Sopenharmony_ci */
7962306a36Sopenharmony_cistatic inline block_t free_segs_blk_count_zoned(struct f2fs_sb_info *sbi)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	block_t free_seg_blks = 0;
8262306a36Sopenharmony_ci	struct free_segmap_info *free_i = FREE_I(sbi);
8362306a36Sopenharmony_ci	int j;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	spin_lock(&free_i->segmap_lock);
8662306a36Sopenharmony_ci	for (j = 0; j < MAIN_SEGS(sbi); j++)
8762306a36Sopenharmony_ci		if (!test_bit(j, free_i->free_segmap))
8862306a36Sopenharmony_ci			free_seg_blks += f2fs_usable_blks_in_seg(sbi, j);
8962306a36Sopenharmony_ci	spin_unlock(&free_i->segmap_lock);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	return free_seg_blks;
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic inline block_t free_segs_blk_count(struct f2fs_sb_info *sbi)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	if (f2fs_sb_has_blkzoned(sbi))
9762306a36Sopenharmony_ci		return free_segs_blk_count_zoned(sbi);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	return free_segments(sbi) << sbi->log_blocks_per_seg;
10062306a36Sopenharmony_ci}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistatic inline block_t free_user_blocks(struct f2fs_sb_info *sbi)
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	block_t free_blks, ovp_blks;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	free_blks = free_segs_blk_count(sbi);
10762306a36Sopenharmony_ci	ovp_blks = overprovision_segments(sbi) << sbi->log_blocks_per_seg;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	if (free_blks < ovp_blks)
11062306a36Sopenharmony_ci		return 0;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	return free_blks - ovp_blks;
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic inline block_t limit_invalid_user_blocks(block_t user_block_count)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	return (long)(user_block_count * LIMIT_INVALID_BLOCK) / 100;
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic inline block_t limit_free_user_blocks(block_t reclaimable_user_blocks)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	return (long)(reclaimable_user_blocks * LIMIT_FREE_BLOCK) / 100;
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic inline void increase_sleep_time(struct f2fs_gc_kthread *gc_th,
12662306a36Sopenharmony_ci							unsigned int *wait)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	unsigned int min_time = gc_th->min_sleep_time;
12962306a36Sopenharmony_ci	unsigned int max_time = gc_th->max_sleep_time;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	if (*wait == gc_th->no_gc_sleep_time)
13262306a36Sopenharmony_ci		return;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	if ((long long)*wait + (long long)min_time > (long long)max_time)
13562306a36Sopenharmony_ci		*wait = max_time;
13662306a36Sopenharmony_ci	else
13762306a36Sopenharmony_ci		*wait += min_time;
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistatic inline void decrease_sleep_time(struct f2fs_gc_kthread *gc_th,
14162306a36Sopenharmony_ci							unsigned int *wait)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	unsigned int min_time = gc_th->min_sleep_time;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	if (*wait == gc_th->no_gc_sleep_time)
14662306a36Sopenharmony_ci		*wait = gc_th->max_sleep_time;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	if ((long long)*wait - (long long)min_time < (long long)min_time)
14962306a36Sopenharmony_ci		*wait = min_time;
15062306a36Sopenharmony_ci	else
15162306a36Sopenharmony_ci		*wait -= min_time;
15262306a36Sopenharmony_ci}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistatic inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	block_t user_block_count = sbi->user_block_count;
15762306a36Sopenharmony_ci	block_t invalid_user_blocks = user_block_count -
15862306a36Sopenharmony_ci		written_block_count(sbi);
15962306a36Sopenharmony_ci	/*
16062306a36Sopenharmony_ci	 * Background GC is triggered with the following conditions.
16162306a36Sopenharmony_ci	 * 1. There are a number of invalid blocks.
16262306a36Sopenharmony_ci	 * 2. There is not enough free space.
16362306a36Sopenharmony_ci	 */
16462306a36Sopenharmony_ci	return (invalid_user_blocks >
16562306a36Sopenharmony_ci			limit_invalid_user_blocks(user_block_count) &&
16662306a36Sopenharmony_ci		free_user_blocks(sbi) <
16762306a36Sopenharmony_ci			limit_free_user_blocks(invalid_user_blocks));
16862306a36Sopenharmony_ci}
169