18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * fs/f2fs/segment.h
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd.
68c2ecf20Sopenharmony_ci *             http://www.samsung.com/
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#include <linux/blkdev.h>
98c2ecf20Sopenharmony_ci#include <linux/backing-dev.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/* constant macro */
128c2ecf20Sopenharmony_ci#define NULL_SEGNO			((unsigned int)(~0))
138c2ecf20Sopenharmony_ci#define NULL_SECNO			((unsigned int)(~0))
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define DEF_RECLAIM_PREFREE_SEGMENTS	5	/* 5% over total segments */
168c2ecf20Sopenharmony_ci#define DEF_MAX_RECLAIM_PREFREE_SEGMENTS	4096	/* 8GB in maximum */
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define F2FS_MIN_SEGMENTS	9 /* SB + 2 (CP + SIT + NAT) + SSA + MAIN */
198c2ecf20Sopenharmony_ci#define F2FS_MIN_META_SEGMENTS	8 /* SB + 2 (CP + SIT + NAT) + SSA */
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci/* L: Logical segment # in volume, R: Relative segment # in main area */
228c2ecf20Sopenharmony_ci#define GET_L2R_SEGNO(free_i, segno)	((segno) - (free_i)->start_segno)
238c2ecf20Sopenharmony_ci#define GET_R2L_SEGNO(free_i, segno)	((segno) + (free_i)->start_segno)
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define IS_DATASEG(t)	((t) <= CURSEG_COLD_DATA)
268c2ecf20Sopenharmony_ci#define IS_NODESEG(t)	((t) >= CURSEG_HOT_NODE && (t) <= CURSEG_COLD_NODE)
278c2ecf20Sopenharmony_ci#define SE_PAGETYPE(se)	((IS_NODESEG((se)->type) ? NODE : DATA))
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
308c2ecf20Sopenharmony_ci						unsigned short seg_type)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, seg_type >= NR_PERSISTENT_LOG);
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define IS_HOT(t)	((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
368c2ecf20Sopenharmony_ci#define IS_WARM(t)	((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
378c2ecf20Sopenharmony_ci#define IS_COLD(t)	((t) == CURSEG_COLD_NODE || (t) == CURSEG_COLD_DATA)
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#define IS_CURSEG(sbi, seg)						\
408c2ecf20Sopenharmony_ci	(((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) ||	\
418c2ecf20Sopenharmony_ci	 ((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) ||	\
428c2ecf20Sopenharmony_ci	 ((seg) == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) ||	\
438c2ecf20Sopenharmony_ci	 ((seg) == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) ||	\
448c2ecf20Sopenharmony_ci	 ((seg) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) ||	\
458c2ecf20Sopenharmony_ci	 ((seg) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno) ||	\
468c2ecf20Sopenharmony_ci	 ((seg) == CURSEG_I(sbi, CURSEG_COLD_DATA_PINNED)->segno) ||	\
478c2ecf20Sopenharmony_ci	 ((seg) == CURSEG_I(sbi, CURSEG_ALL_DATA_ATGC)->segno))
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define IS_CURSEC(sbi, secno)						\
508c2ecf20Sopenharmony_ci	(((secno) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno /		\
518c2ecf20Sopenharmony_ci	  (sbi)->segs_per_sec) ||	\
528c2ecf20Sopenharmony_ci	 ((secno) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno /		\
538c2ecf20Sopenharmony_ci	  (sbi)->segs_per_sec) ||	\
548c2ecf20Sopenharmony_ci	 ((secno) == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno /		\
558c2ecf20Sopenharmony_ci	  (sbi)->segs_per_sec) ||	\
568c2ecf20Sopenharmony_ci	 ((secno) == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno /		\
578c2ecf20Sopenharmony_ci	  (sbi)->segs_per_sec) ||	\
588c2ecf20Sopenharmony_ci	 ((secno) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno /		\
598c2ecf20Sopenharmony_ci	  (sbi)->segs_per_sec) ||	\
608c2ecf20Sopenharmony_ci	 ((secno) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno /		\
618c2ecf20Sopenharmony_ci	  (sbi)->segs_per_sec) ||	\
628c2ecf20Sopenharmony_ci	 ((secno) == CURSEG_I(sbi, CURSEG_COLD_DATA_PINNED)->segno /	\
638c2ecf20Sopenharmony_ci	  (sbi)->segs_per_sec) ||	\
648c2ecf20Sopenharmony_ci	 ((secno) == CURSEG_I(sbi, CURSEG_ALL_DATA_ATGC)->segno /	\
658c2ecf20Sopenharmony_ci	  (sbi)->segs_per_sec))
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#define MAIN_BLKADDR(sbi)						\
688c2ecf20Sopenharmony_ci	(SM_I(sbi) ? SM_I(sbi)->main_blkaddr : 				\
698c2ecf20Sopenharmony_ci		le32_to_cpu(F2FS_RAW_SUPER(sbi)->main_blkaddr))
708c2ecf20Sopenharmony_ci#define SEG0_BLKADDR(sbi)						\
718c2ecf20Sopenharmony_ci	(SM_I(sbi) ? SM_I(sbi)->seg0_blkaddr : 				\
728c2ecf20Sopenharmony_ci		le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment0_blkaddr))
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci#define MAIN_SEGS(sbi)	(SM_I(sbi)->main_segments)
758c2ecf20Sopenharmony_ci#define MAIN_SECS(sbi)	((sbi)->total_sections)
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci#define TOTAL_SEGS(sbi)							\
788c2ecf20Sopenharmony_ci	(SM_I(sbi) ? SM_I(sbi)->segment_count : 				\
798c2ecf20Sopenharmony_ci		le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count))
808c2ecf20Sopenharmony_ci#define TOTAL_BLKS(sbi)	(TOTAL_SEGS(sbi) << (sbi)->log_blocks_per_seg)
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci#define MAX_BLKADDR(sbi)	(SEG0_BLKADDR(sbi) + TOTAL_BLKS(sbi))
838c2ecf20Sopenharmony_ci#define SEGMENT_SIZE(sbi)	(1ULL << ((sbi)->log_blocksize +	\
848c2ecf20Sopenharmony_ci					(sbi)->log_blocks_per_seg))
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci#define START_BLOCK(sbi, segno)	(SEG0_BLKADDR(sbi) +			\
878c2ecf20Sopenharmony_ci	 (GET_R2L_SEGNO(FREE_I(sbi), segno) << (sbi)->log_blocks_per_seg))
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci#define NEXT_FREE_BLKADDR(sbi, curseg)					\
908c2ecf20Sopenharmony_ci	(START_BLOCK(sbi, (curseg)->segno) + (curseg)->next_blkoff)
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci#define GET_SEGOFF_FROM_SEG0(sbi, blk_addr)	((blk_addr) - SEG0_BLKADDR(sbi))
938c2ecf20Sopenharmony_ci#define GET_SEGNO_FROM_SEG0(sbi, blk_addr)				\
948c2ecf20Sopenharmony_ci	(GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> (sbi)->log_blocks_per_seg)
958c2ecf20Sopenharmony_ci#define GET_BLKOFF_FROM_SEG0(sbi, blk_addr)				\
968c2ecf20Sopenharmony_ci	(GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & ((sbi)->blocks_per_seg - 1))
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci#define GET_SEGNO(sbi, blk_addr)					\
998c2ecf20Sopenharmony_ci	((!__is_valid_data_blkaddr(blk_addr)) ?			\
1008c2ecf20Sopenharmony_ci	NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi),			\
1018c2ecf20Sopenharmony_ci		GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
1028c2ecf20Sopenharmony_ci#define BLKS_PER_SEC(sbi)					\
1038c2ecf20Sopenharmony_ci	((sbi)->segs_per_sec * (sbi)->blocks_per_seg)
1048c2ecf20Sopenharmony_ci#define CAP_BLKS_PER_SEC(sbi)					\
1058c2ecf20Sopenharmony_ci	((sbi)->segs_per_sec * (sbi)->blocks_per_seg -		\
1068c2ecf20Sopenharmony_ci	 (sbi)->unusable_blocks_per_sec)
1078c2ecf20Sopenharmony_ci#define CAP_SEGS_PER_SEC(sbi)					\
1088c2ecf20Sopenharmony_ci	((sbi)->segs_per_sec - ((sbi)->unusable_blocks_per_sec >>\
1098c2ecf20Sopenharmony_ci	(sbi)->log_blocks_per_seg))
1108c2ecf20Sopenharmony_ci#define GET_SEC_FROM_SEG(sbi, segno)				\
1118c2ecf20Sopenharmony_ci	(((segno) == -1) ? -1: (segno) / (sbi)->segs_per_sec)
1128c2ecf20Sopenharmony_ci#define GET_SEG_FROM_SEC(sbi, secno)				\
1138c2ecf20Sopenharmony_ci	((secno) * (sbi)->segs_per_sec)
1148c2ecf20Sopenharmony_ci#define GET_ZONE_FROM_SEC(sbi, secno)				\
1158c2ecf20Sopenharmony_ci	(((secno) == -1) ? -1: (secno) / (sbi)->secs_per_zone)
1168c2ecf20Sopenharmony_ci#define GET_ZONE_FROM_SEG(sbi, segno)				\
1178c2ecf20Sopenharmony_ci	GET_ZONE_FROM_SEC(sbi, GET_SEC_FROM_SEG(sbi, segno))
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci#define GET_SUM_BLOCK(sbi, segno)				\
1208c2ecf20Sopenharmony_ci	((sbi)->sm_info->ssa_blkaddr + (segno))
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci#define GET_SUM_TYPE(footer) ((footer)->entry_type)
1238c2ecf20Sopenharmony_ci#define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type))
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci#define SIT_ENTRY_OFFSET(sit_i, segno)					\
1268c2ecf20Sopenharmony_ci	((segno) % (sit_i)->sents_per_block)
1278c2ecf20Sopenharmony_ci#define SIT_BLOCK_OFFSET(segno)					\
1288c2ecf20Sopenharmony_ci	((segno) / SIT_ENTRY_PER_BLOCK)
1298c2ecf20Sopenharmony_ci#define	START_SEGNO(segno)		\
1308c2ecf20Sopenharmony_ci	(SIT_BLOCK_OFFSET(segno) * SIT_ENTRY_PER_BLOCK)
1318c2ecf20Sopenharmony_ci#define SIT_BLK_CNT(sbi)			\
1328c2ecf20Sopenharmony_ci	DIV_ROUND_UP(MAIN_SEGS(sbi), SIT_ENTRY_PER_BLOCK)
1338c2ecf20Sopenharmony_ci#define f2fs_bitmap_size(nr)			\
1348c2ecf20Sopenharmony_ci	(BITS_TO_LONGS(nr) * sizeof(unsigned long))
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci#define SECTOR_FROM_BLOCK(blk_addr)					\
1378c2ecf20Sopenharmony_ci	(((sector_t)blk_addr) << F2FS_LOG_SECTORS_PER_BLOCK)
1388c2ecf20Sopenharmony_ci#define SECTOR_TO_BLOCK(sectors)					\
1398c2ecf20Sopenharmony_ci	((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK)
1408c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_GRADING_SSR
1418c2ecf20Sopenharmony_ci#define KBS_PER_SEGMENT 2048
1428c2ecf20Sopenharmony_ci#define SSR_MIN_BLKS_LIMIT (16 << 18)	/* 16G */
1438c2ecf20Sopenharmony_ci#define SSR_CONTIG_DIRTY_NUMS	32	/* Dirty pages for LFS alloction in grading ssr. */
1448c2ecf20Sopenharmony_ci#define SSR_CONTIG_LARGE	256	/* Larege files */
1458c2ecf20Sopenharmony_ci#endif
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cienum {
1488c2ecf20Sopenharmony_ci	SEQ_NONE,
1498c2ecf20Sopenharmony_ci	SEQ_32BLKS,
1508c2ecf20Sopenharmony_ci	SEQ_256BLKS
1518c2ecf20Sopenharmony_ci};
1528c2ecf20Sopenharmony_ci/*
1538c2ecf20Sopenharmony_ci * indicate a block allocation direction: RIGHT and LEFT.
1548c2ecf20Sopenharmony_ci * RIGHT means allocating new sections towards the end of volume.
1558c2ecf20Sopenharmony_ci * LEFT means the opposite direction.
1568c2ecf20Sopenharmony_ci */
1578c2ecf20Sopenharmony_cienum {
1588c2ecf20Sopenharmony_ci	ALLOC_RIGHT = 0,
1598c2ecf20Sopenharmony_ci	ALLOC_LEFT
1608c2ecf20Sopenharmony_ci};
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci/*
1638c2ecf20Sopenharmony_ci * In the victim_sel_policy->alloc_mode, there are two block allocation modes.
1648c2ecf20Sopenharmony_ci * LFS writes data sequentially with cleaning operations.
1658c2ecf20Sopenharmony_ci * SSR (Slack Space Recycle) reuses obsolete space without cleaning operations.
1668c2ecf20Sopenharmony_ci * AT_SSR (Age Threshold based Slack Space Recycle) merges fragments into
1678c2ecf20Sopenharmony_ci * fragmented segment which has similar aging degree.
1688c2ecf20Sopenharmony_ci */
1698c2ecf20Sopenharmony_cienum {
1708c2ecf20Sopenharmony_ci	LFS = 0,
1718c2ecf20Sopenharmony_ci	SSR,
1728c2ecf20Sopenharmony_ci	AT_SSR,
1738c2ecf20Sopenharmony_ci};
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci/*
1768c2ecf20Sopenharmony_ci * In the victim_sel_policy->gc_mode, there are two gc, aka cleaning, modes.
1778c2ecf20Sopenharmony_ci * GC_CB is based on cost-benefit algorithm.
1788c2ecf20Sopenharmony_ci * GC_GREEDY is based on greedy algorithm.
1798c2ecf20Sopenharmony_ci * GC_AT is based on age-threshold algorithm.
1808c2ecf20Sopenharmony_ci */
1818c2ecf20Sopenharmony_cienum {
1828c2ecf20Sopenharmony_ci	GC_CB = 0,
1838c2ecf20Sopenharmony_ci	GC_GREEDY,
1848c2ecf20Sopenharmony_ci	GC_AT,
1858c2ecf20Sopenharmony_ci	ALLOC_NEXT,
1868c2ecf20Sopenharmony_ci	FLUSH_DEVICE,
1878c2ecf20Sopenharmony_ci	MAX_GC_POLICY,
1888c2ecf20Sopenharmony_ci};
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci/*
1918c2ecf20Sopenharmony_ci * BG_GC means the background cleaning job.
1928c2ecf20Sopenharmony_ci * FG_GC means the on-demand cleaning job.
1938c2ecf20Sopenharmony_ci * FORCE_FG_GC means on-demand cleaning job in background.
1948c2ecf20Sopenharmony_ci */
1958c2ecf20Sopenharmony_cienum {
1968c2ecf20Sopenharmony_ci	BG_GC = 0,
1978c2ecf20Sopenharmony_ci	FG_GC,
1988c2ecf20Sopenharmony_ci	FORCE_FG_GC,
1998c2ecf20Sopenharmony_ci};
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_GRADING_SSR
2028c2ecf20Sopenharmony_cienum {
2038c2ecf20Sopenharmony_ci	GRADING_SSR_OFF = 0,
2048c2ecf20Sopenharmony_ci	GRADING_SSR_ON
2058c2ecf20Sopenharmony_ci};
2068c2ecf20Sopenharmony_ci#endif
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci/* for a function parameter to select a victim segment */
2098c2ecf20Sopenharmony_cistruct victim_sel_policy {
2108c2ecf20Sopenharmony_ci	int alloc_mode;			/* LFS or SSR */
2118c2ecf20Sopenharmony_ci	int gc_mode;			/* GC_CB or GC_GREEDY */
2128c2ecf20Sopenharmony_ci	unsigned long *dirty_bitmap;	/* dirty segment/section bitmap */
2138c2ecf20Sopenharmony_ci	unsigned int max_search;	/*
2148c2ecf20Sopenharmony_ci					 * maximum # of segments/sections
2158c2ecf20Sopenharmony_ci					 * to search
2168c2ecf20Sopenharmony_ci					 */
2178c2ecf20Sopenharmony_ci	unsigned int offset;		/* last scanned bitmap offset */
2188c2ecf20Sopenharmony_ci	unsigned int ofs_unit;		/* bitmap search unit */
2198c2ecf20Sopenharmony_ci	unsigned int min_cost;		/* minimum cost */
2208c2ecf20Sopenharmony_ci	unsigned long long oldest_age;	/* oldest age of segments having the same min cost */
2218c2ecf20Sopenharmony_ci	unsigned int min_segno;		/* segment # having min. cost */
2228c2ecf20Sopenharmony_ci	unsigned long long age;		/* mtime of GCed section*/
2238c2ecf20Sopenharmony_ci	unsigned long long age_threshold;/* age threshold */
2248c2ecf20Sopenharmony_ci};
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistruct seg_entry {
2278c2ecf20Sopenharmony_ci	unsigned int type:6;		/* segment type like CURSEG_XXX_TYPE */
2288c2ecf20Sopenharmony_ci	unsigned int valid_blocks:10;	/* # of valid blocks */
2298c2ecf20Sopenharmony_ci	unsigned int ckpt_valid_blocks:10;	/* # of valid blocks last cp */
2308c2ecf20Sopenharmony_ci	unsigned int padding:6;		/* padding */
2318c2ecf20Sopenharmony_ci	unsigned char *cur_valid_map;	/* validity bitmap of blocks */
2328c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
2338c2ecf20Sopenharmony_ci	unsigned char *cur_valid_map_mir;	/* mirror of current valid bitmap */
2348c2ecf20Sopenharmony_ci#endif
2358c2ecf20Sopenharmony_ci	/*
2368c2ecf20Sopenharmony_ci	 * # of valid blocks and the validity bitmap stored in the last
2378c2ecf20Sopenharmony_ci	 * checkpoint pack. This information is used by the SSR mode.
2388c2ecf20Sopenharmony_ci	 */
2398c2ecf20Sopenharmony_ci	unsigned char *ckpt_valid_map;	/* validity bitmap of blocks last cp */
2408c2ecf20Sopenharmony_ci	unsigned char *discard_map;
2418c2ecf20Sopenharmony_ci	unsigned long long mtime;	/* modification time of the segment */
2428c2ecf20Sopenharmony_ci};
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_cistruct sec_entry {
2458c2ecf20Sopenharmony_ci	unsigned int valid_blocks;	/* # of valid blocks in a section */
2468c2ecf20Sopenharmony_ci};
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_cistruct segment_allocation {
2498c2ecf20Sopenharmony_ci	void (*allocate_segment)(struct f2fs_sb_info *, int, bool, int);
2508c2ecf20Sopenharmony_ci};
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci#define MAX_SKIP_GC_COUNT			16
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistruct inmem_pages {
2558c2ecf20Sopenharmony_ci	struct list_head list;
2568c2ecf20Sopenharmony_ci	struct page *page;
2578c2ecf20Sopenharmony_ci	block_t old_addr;		/* for revoking when fail to commit */
2588c2ecf20Sopenharmony_ci};
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cistruct sit_info {
2618c2ecf20Sopenharmony_ci	const struct segment_allocation *s_ops;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	block_t sit_base_addr;		/* start block address of SIT area */
2648c2ecf20Sopenharmony_ci	block_t sit_blocks;		/* # of blocks used by SIT area */
2658c2ecf20Sopenharmony_ci	block_t written_valid_blocks;	/* # of valid blocks in main area */
2668c2ecf20Sopenharmony_ci	char *bitmap;			/* all bitmaps pointer */
2678c2ecf20Sopenharmony_ci	char *sit_bitmap;		/* SIT bitmap pointer */
2688c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
2698c2ecf20Sopenharmony_ci	char *sit_bitmap_mir;		/* SIT bitmap mirror */
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	/* bitmap of segments to be ignored by GC in case of errors */
2728c2ecf20Sopenharmony_ci	unsigned long *invalid_segmap;
2738c2ecf20Sopenharmony_ci#endif
2748c2ecf20Sopenharmony_ci	unsigned int bitmap_size;	/* SIT bitmap size */
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	unsigned long *tmp_map;			/* bitmap for temporal use */
2778c2ecf20Sopenharmony_ci	unsigned long *dirty_sentries_bitmap;	/* bitmap for dirty sentries */
2788c2ecf20Sopenharmony_ci	unsigned int dirty_sentries;		/* # of dirty sentries */
2798c2ecf20Sopenharmony_ci	unsigned int sents_per_block;		/* # of SIT entries per block */
2808c2ecf20Sopenharmony_ci	struct rw_semaphore sentry_lock;	/* to protect SIT cache */
2818c2ecf20Sopenharmony_ci	struct seg_entry *sentries;		/* SIT segment-level cache */
2828c2ecf20Sopenharmony_ci	struct sec_entry *sec_entries;		/* SIT section-level cache */
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	/* for cost-benefit algorithm in cleaning procedure */
2858c2ecf20Sopenharmony_ci	unsigned long long elapsed_time;	/* elapsed time after mount */
2868c2ecf20Sopenharmony_ci	unsigned long long mounted_time;	/* mount time */
2878c2ecf20Sopenharmony_ci	unsigned long long min_mtime;		/* min. modification time */
2888c2ecf20Sopenharmony_ci	unsigned long long max_mtime;		/* max. modification time */
2898c2ecf20Sopenharmony_ci	unsigned long long dirty_min_mtime;	/* rerange candidates in GC_AT */
2908c2ecf20Sopenharmony_ci	unsigned long long dirty_max_mtime;	/* rerange candidates in GC_AT */
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	unsigned int last_victim[MAX_GC_POLICY]; /* last victim segment # */
2938c2ecf20Sopenharmony_ci};
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_cistruct free_segmap_info {
2968c2ecf20Sopenharmony_ci	unsigned int start_segno;	/* start segment number logically */
2978c2ecf20Sopenharmony_ci	unsigned int free_segments;	/* # of free segments */
2988c2ecf20Sopenharmony_ci	unsigned int free_sections;	/* # of free sections */
2998c2ecf20Sopenharmony_ci	spinlock_t segmap_lock;		/* free segmap lock */
3008c2ecf20Sopenharmony_ci	unsigned long *free_segmap;	/* free segment bitmap */
3018c2ecf20Sopenharmony_ci	unsigned long *free_secmap;	/* free section bitmap */
3028c2ecf20Sopenharmony_ci};
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci/* Notice: The order of dirty type is same with CURSEG_XXX in f2fs.h */
3058c2ecf20Sopenharmony_cienum dirty_type {
3068c2ecf20Sopenharmony_ci	DIRTY_HOT_DATA,		/* dirty segments assigned as hot data logs */
3078c2ecf20Sopenharmony_ci	DIRTY_WARM_DATA,	/* dirty segments assigned as warm data logs */
3088c2ecf20Sopenharmony_ci	DIRTY_COLD_DATA,	/* dirty segments assigned as cold data logs */
3098c2ecf20Sopenharmony_ci	DIRTY_HOT_NODE,		/* dirty segments assigned as hot node logs */
3108c2ecf20Sopenharmony_ci	DIRTY_WARM_NODE,	/* dirty segments assigned as warm node logs */
3118c2ecf20Sopenharmony_ci	DIRTY_COLD_NODE,	/* dirty segments assigned as cold node logs */
3128c2ecf20Sopenharmony_ci	DIRTY,			/* to count # of dirty segments */
3138c2ecf20Sopenharmony_ci	PRE,			/* to count # of entirely obsolete segments */
3148c2ecf20Sopenharmony_ci	NR_DIRTY_TYPE
3158c2ecf20Sopenharmony_ci};
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistruct dirty_seglist_info {
3188c2ecf20Sopenharmony_ci	const struct victim_selection *v_ops;	/* victim selction operation */
3198c2ecf20Sopenharmony_ci	unsigned long *dirty_segmap[NR_DIRTY_TYPE];
3208c2ecf20Sopenharmony_ci	unsigned long *dirty_secmap;
3218c2ecf20Sopenharmony_ci	struct mutex seglist_lock;		/* lock for segment bitmaps */
3228c2ecf20Sopenharmony_ci	int nr_dirty[NR_DIRTY_TYPE];		/* # of dirty segments */
3238c2ecf20Sopenharmony_ci	unsigned long *victim_secmap;		/* background GC victims */
3248c2ecf20Sopenharmony_ci};
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci/* victim selection function for cleaning and SSR */
3278c2ecf20Sopenharmony_cistruct victim_selection {
3288c2ecf20Sopenharmony_ci	int (*get_victim)(struct f2fs_sb_info *, unsigned int *,
3298c2ecf20Sopenharmony_ci					int, int, char, unsigned long long);
3308c2ecf20Sopenharmony_ci};
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci/* for active log information */
3338c2ecf20Sopenharmony_cistruct curseg_info {
3348c2ecf20Sopenharmony_ci	struct mutex curseg_mutex;		/* lock for consistency */
3358c2ecf20Sopenharmony_ci	struct f2fs_summary_block *sum_blk;	/* cached summary block */
3368c2ecf20Sopenharmony_ci	struct rw_semaphore journal_rwsem;	/* protect journal area */
3378c2ecf20Sopenharmony_ci	struct f2fs_journal *journal;		/* cached journal info */
3388c2ecf20Sopenharmony_ci	unsigned char alloc_type;		/* current allocation type */
3398c2ecf20Sopenharmony_ci	unsigned short seg_type;		/* segment type like CURSEG_XXX_TYPE */
3408c2ecf20Sopenharmony_ci	unsigned int segno;			/* current segment number */
3418c2ecf20Sopenharmony_ci	unsigned short next_blkoff;		/* next block offset to write */
3428c2ecf20Sopenharmony_ci	unsigned int zone;			/* current zone number */
3438c2ecf20Sopenharmony_ci	unsigned int next_segno;		/* preallocated segment */
3448c2ecf20Sopenharmony_ci	bool inited;				/* indicate inmem log is inited */
3458c2ecf20Sopenharmony_ci};
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_cistruct sit_entry_set {
3488c2ecf20Sopenharmony_ci	struct list_head set_list;	/* link with all sit sets */
3498c2ecf20Sopenharmony_ci	unsigned int start_segno;	/* start segno of sits in set */
3508c2ecf20Sopenharmony_ci	unsigned int entry_cnt;		/* the # of sit entries in set */
3518c2ecf20Sopenharmony_ci};
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci/*
3548c2ecf20Sopenharmony_ci * inline functions
3558c2ecf20Sopenharmony_ci */
3568c2ecf20Sopenharmony_cistatic inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	return (struct curseg_info *)(SM_I(sbi)->curseg_array + type);
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cistatic inline struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi,
3628c2ecf20Sopenharmony_ci						unsigned int segno)
3638c2ecf20Sopenharmony_ci{
3648c2ecf20Sopenharmony_ci	struct sit_info *sit_i = SIT_I(sbi);
3658c2ecf20Sopenharmony_ci	return &sit_i->sentries[segno];
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_cistatic inline struct sec_entry *get_sec_entry(struct f2fs_sb_info *sbi,
3698c2ecf20Sopenharmony_ci						unsigned int segno)
3708c2ecf20Sopenharmony_ci{
3718c2ecf20Sopenharmony_ci	struct sit_info *sit_i = SIT_I(sbi);
3728c2ecf20Sopenharmony_ci	return &sit_i->sec_entries[GET_SEC_FROM_SEG(sbi, segno)];
3738c2ecf20Sopenharmony_ci}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_cistatic inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi,
3768c2ecf20Sopenharmony_ci				unsigned int segno, bool use_section)
3778c2ecf20Sopenharmony_ci{
3788c2ecf20Sopenharmony_ci	/*
3798c2ecf20Sopenharmony_ci	 * In order to get # of valid blocks in a section instantly from many
3808c2ecf20Sopenharmony_ci	 * segments, f2fs manages two counting structures separately.
3818c2ecf20Sopenharmony_ci	 */
3828c2ecf20Sopenharmony_ci	if (use_section && __is_large_section(sbi))
3838c2ecf20Sopenharmony_ci		return get_sec_entry(sbi, segno)->valid_blocks;
3848c2ecf20Sopenharmony_ci	else
3858c2ecf20Sopenharmony_ci		return get_seg_entry(sbi, segno)->valid_blocks;
3868c2ecf20Sopenharmony_ci}
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_cistatic inline unsigned int get_ckpt_valid_blocks(struct f2fs_sb_info *sbi,
3898c2ecf20Sopenharmony_ci				unsigned int segno, bool use_section)
3908c2ecf20Sopenharmony_ci{
3918c2ecf20Sopenharmony_ci	if (use_section && __is_large_section(sbi)) {
3928c2ecf20Sopenharmony_ci		unsigned int start_segno = START_SEGNO(segno);
3938c2ecf20Sopenharmony_ci		unsigned int blocks = 0;
3948c2ecf20Sopenharmony_ci		int i;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci		for (i = 0; i < sbi->segs_per_sec; i++, start_segno++) {
3978c2ecf20Sopenharmony_ci			struct seg_entry *se = get_seg_entry(sbi, start_segno);
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci			blocks += se->ckpt_valid_blocks;
4008c2ecf20Sopenharmony_ci		}
4018c2ecf20Sopenharmony_ci		return blocks;
4028c2ecf20Sopenharmony_ci	}
4038c2ecf20Sopenharmony_ci	return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
4048c2ecf20Sopenharmony_ci}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_cistatic inline void seg_info_from_raw_sit(struct seg_entry *se,
4078c2ecf20Sopenharmony_ci					struct f2fs_sit_entry *rs)
4088c2ecf20Sopenharmony_ci{
4098c2ecf20Sopenharmony_ci	se->valid_blocks = GET_SIT_VBLOCKS(rs);
4108c2ecf20Sopenharmony_ci	se->ckpt_valid_blocks = GET_SIT_VBLOCKS(rs);
4118c2ecf20Sopenharmony_ci	memcpy(se->cur_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
4128c2ecf20Sopenharmony_ci	memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
4138c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
4148c2ecf20Sopenharmony_ci	memcpy(se->cur_valid_map_mir, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
4158c2ecf20Sopenharmony_ci#endif
4168c2ecf20Sopenharmony_ci	se->type = GET_SIT_TYPE(rs);
4178c2ecf20Sopenharmony_ci	se->mtime = le64_to_cpu(rs->mtime);
4188c2ecf20Sopenharmony_ci}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_cistatic inline void __seg_info_to_raw_sit(struct seg_entry *se,
4218c2ecf20Sopenharmony_ci					struct f2fs_sit_entry *rs)
4228c2ecf20Sopenharmony_ci{
4238c2ecf20Sopenharmony_ci	unsigned short raw_vblocks = (se->type << SIT_VBLOCKS_SHIFT) |
4248c2ecf20Sopenharmony_ci					se->valid_blocks;
4258c2ecf20Sopenharmony_ci	rs->vblocks = cpu_to_le16(raw_vblocks);
4268c2ecf20Sopenharmony_ci	memcpy(rs->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE);
4278c2ecf20Sopenharmony_ci	rs->mtime = cpu_to_le64(se->mtime);
4288c2ecf20Sopenharmony_ci}
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_cistatic inline void seg_info_to_sit_page(struct f2fs_sb_info *sbi,
4318c2ecf20Sopenharmony_ci				struct page *page, unsigned int start)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	struct f2fs_sit_block *raw_sit;
4348c2ecf20Sopenharmony_ci	struct seg_entry *se;
4358c2ecf20Sopenharmony_ci	struct f2fs_sit_entry *rs;
4368c2ecf20Sopenharmony_ci	unsigned int end = min(start + SIT_ENTRY_PER_BLOCK,
4378c2ecf20Sopenharmony_ci					(unsigned long)MAIN_SEGS(sbi));
4388c2ecf20Sopenharmony_ci	int i;
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	raw_sit = (struct f2fs_sit_block *)page_address(page);
4418c2ecf20Sopenharmony_ci	memset(raw_sit, 0, PAGE_SIZE);
4428c2ecf20Sopenharmony_ci	for (i = 0; i < end - start; i++) {
4438c2ecf20Sopenharmony_ci		rs = &raw_sit->entries[i];
4448c2ecf20Sopenharmony_ci		se = get_seg_entry(sbi, start + i);
4458c2ecf20Sopenharmony_ci		__seg_info_to_raw_sit(se, rs);
4468c2ecf20Sopenharmony_ci	}
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_cistatic inline void seg_info_to_raw_sit(struct seg_entry *se,
4508c2ecf20Sopenharmony_ci					struct f2fs_sit_entry *rs)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	__seg_info_to_raw_sit(se, rs);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
4558c2ecf20Sopenharmony_ci	se->ckpt_valid_blocks = se->valid_blocks;
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic inline unsigned int find_next_inuse(struct free_segmap_info *free_i,
4598c2ecf20Sopenharmony_ci		unsigned int max, unsigned int segno)
4608c2ecf20Sopenharmony_ci{
4618c2ecf20Sopenharmony_ci	unsigned int ret;
4628c2ecf20Sopenharmony_ci	spin_lock(&free_i->segmap_lock);
4638c2ecf20Sopenharmony_ci	ret = find_next_bit(free_i->free_segmap, max, segno);
4648c2ecf20Sopenharmony_ci	spin_unlock(&free_i->segmap_lock);
4658c2ecf20Sopenharmony_ci	return ret;
4668c2ecf20Sopenharmony_ci}
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_cistatic inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno)
4698c2ecf20Sopenharmony_ci{
4708c2ecf20Sopenharmony_ci	struct free_segmap_info *free_i = FREE_I(sbi);
4718c2ecf20Sopenharmony_ci	unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
4728c2ecf20Sopenharmony_ci	unsigned int start_segno = GET_SEG_FROM_SEC(sbi, secno);
4738c2ecf20Sopenharmony_ci	unsigned int next;
4748c2ecf20Sopenharmony_ci	unsigned int usable_segs = f2fs_usable_segs_in_sec(sbi, segno);
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	spin_lock(&free_i->segmap_lock);
4778c2ecf20Sopenharmony_ci	clear_bit(segno, free_i->free_segmap);
4788c2ecf20Sopenharmony_ci	free_i->free_segments++;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	next = find_next_bit(free_i->free_segmap,
4818c2ecf20Sopenharmony_ci			start_segno + sbi->segs_per_sec, start_segno);
4828c2ecf20Sopenharmony_ci	if (next >= start_segno + usable_segs) {
4838c2ecf20Sopenharmony_ci		clear_bit(secno, free_i->free_secmap);
4848c2ecf20Sopenharmony_ci		free_i->free_sections++;
4858c2ecf20Sopenharmony_ci	}
4868c2ecf20Sopenharmony_ci	spin_unlock(&free_i->segmap_lock);
4878c2ecf20Sopenharmony_ci}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_cistatic inline void __set_inuse(struct f2fs_sb_info *sbi,
4908c2ecf20Sopenharmony_ci		unsigned int segno)
4918c2ecf20Sopenharmony_ci{
4928c2ecf20Sopenharmony_ci	struct free_segmap_info *free_i = FREE_I(sbi);
4938c2ecf20Sopenharmony_ci	unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	set_bit(segno, free_i->free_segmap);
4968c2ecf20Sopenharmony_ci	free_i->free_segments--;
4978c2ecf20Sopenharmony_ci	if (!test_and_set_bit(secno, free_i->free_secmap))
4988c2ecf20Sopenharmony_ci		free_i->free_sections--;
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic inline void __set_test_and_free(struct f2fs_sb_info *sbi,
5028c2ecf20Sopenharmony_ci		unsigned int segno, bool inmem)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	struct free_segmap_info *free_i = FREE_I(sbi);
5058c2ecf20Sopenharmony_ci	unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
5068c2ecf20Sopenharmony_ci	unsigned int start_segno = GET_SEG_FROM_SEC(sbi, secno);
5078c2ecf20Sopenharmony_ci	unsigned int next;
5088c2ecf20Sopenharmony_ci	unsigned int usable_segs = f2fs_usable_segs_in_sec(sbi, segno);
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	spin_lock(&free_i->segmap_lock);
5118c2ecf20Sopenharmony_ci	if (test_and_clear_bit(segno, free_i->free_segmap)) {
5128c2ecf20Sopenharmony_ci		free_i->free_segments++;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci		if (!inmem && IS_CURSEC(sbi, secno))
5158c2ecf20Sopenharmony_ci			goto skip_free;
5168c2ecf20Sopenharmony_ci		next = find_next_bit(free_i->free_segmap,
5178c2ecf20Sopenharmony_ci				start_segno + sbi->segs_per_sec, start_segno);
5188c2ecf20Sopenharmony_ci		if (next >= start_segno + usable_segs) {
5198c2ecf20Sopenharmony_ci			if (test_and_clear_bit(secno, free_i->free_secmap))
5208c2ecf20Sopenharmony_ci				free_i->free_sections++;
5218c2ecf20Sopenharmony_ci		}
5228c2ecf20Sopenharmony_ci	}
5238c2ecf20Sopenharmony_ciskip_free:
5248c2ecf20Sopenharmony_ci	spin_unlock(&free_i->segmap_lock);
5258c2ecf20Sopenharmony_ci}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_cistatic inline void __set_test_and_inuse(struct f2fs_sb_info *sbi,
5288c2ecf20Sopenharmony_ci		unsigned int segno)
5298c2ecf20Sopenharmony_ci{
5308c2ecf20Sopenharmony_ci	struct free_segmap_info *free_i = FREE_I(sbi);
5318c2ecf20Sopenharmony_ci	unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	spin_lock(&free_i->segmap_lock);
5348c2ecf20Sopenharmony_ci	if (!test_and_set_bit(segno, free_i->free_segmap)) {
5358c2ecf20Sopenharmony_ci		free_i->free_segments--;
5368c2ecf20Sopenharmony_ci		if (!test_and_set_bit(secno, free_i->free_secmap))
5378c2ecf20Sopenharmony_ci			free_i->free_sections--;
5388c2ecf20Sopenharmony_ci	}
5398c2ecf20Sopenharmony_ci	spin_unlock(&free_i->segmap_lock);
5408c2ecf20Sopenharmony_ci}
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_cistatic inline void get_sit_bitmap(struct f2fs_sb_info *sbi,
5438c2ecf20Sopenharmony_ci		void *dst_addr)
5448c2ecf20Sopenharmony_ci{
5458c2ecf20Sopenharmony_ci	struct sit_info *sit_i = SIT_I(sbi);
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
5488c2ecf20Sopenharmony_ci	if (memcmp(sit_i->sit_bitmap, sit_i->sit_bitmap_mir,
5498c2ecf20Sopenharmony_ci						sit_i->bitmap_size))
5508c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, 1);
5518c2ecf20Sopenharmony_ci#endif
5528c2ecf20Sopenharmony_ci	memcpy(dst_addr, sit_i->sit_bitmap, sit_i->bitmap_size);
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_cistatic inline block_t written_block_count(struct f2fs_sb_info *sbi)
5568c2ecf20Sopenharmony_ci{
5578c2ecf20Sopenharmony_ci	return SIT_I(sbi)->written_valid_blocks;
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_cistatic inline unsigned int free_segments(struct f2fs_sb_info *sbi)
5618c2ecf20Sopenharmony_ci{
5628c2ecf20Sopenharmony_ci	return FREE_I(sbi)->free_segments;
5638c2ecf20Sopenharmony_ci}
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_cistatic inline unsigned int reserved_segments(struct f2fs_sb_info *sbi)
5668c2ecf20Sopenharmony_ci{
5678c2ecf20Sopenharmony_ci	return SM_I(sbi)->reserved_segments +
5688c2ecf20Sopenharmony_ci			SM_I(sbi)->additional_reserved_segments;
5698c2ecf20Sopenharmony_ci}
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_cistatic inline unsigned int free_sections(struct f2fs_sb_info *sbi)
5728c2ecf20Sopenharmony_ci{
5738c2ecf20Sopenharmony_ci	return FREE_I(sbi)->free_sections;
5748c2ecf20Sopenharmony_ci}
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_cistatic inline unsigned int prefree_segments(struct f2fs_sb_info *sbi)
5778c2ecf20Sopenharmony_ci{
5788c2ecf20Sopenharmony_ci	return DIRTY_I(sbi)->nr_dirty[PRE];
5798c2ecf20Sopenharmony_ci}
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_cistatic inline unsigned int dirty_segments(struct f2fs_sb_info *sbi)
5828c2ecf20Sopenharmony_ci{
5838c2ecf20Sopenharmony_ci	return DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_DATA] +
5848c2ecf20Sopenharmony_ci		DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_DATA] +
5858c2ecf20Sopenharmony_ci		DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_DATA] +
5868c2ecf20Sopenharmony_ci		DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_NODE] +
5878c2ecf20Sopenharmony_ci		DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_NODE] +
5888c2ecf20Sopenharmony_ci		DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_NODE];
5898c2ecf20Sopenharmony_ci}
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_cistatic inline int overprovision_segments(struct f2fs_sb_info *sbi)
5928c2ecf20Sopenharmony_ci{
5938c2ecf20Sopenharmony_ci	return SM_I(sbi)->ovp_segments;
5948c2ecf20Sopenharmony_ci}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_cistatic inline int reserved_sections(struct f2fs_sb_info *sbi)
5978c2ecf20Sopenharmony_ci{
5988c2ecf20Sopenharmony_ci	return GET_SEC_FROM_SEG(sbi, reserved_segments(sbi));
5998c2ecf20Sopenharmony_ci}
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_cistatic inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi,
6028c2ecf20Sopenharmony_ci			unsigned int node_blocks, unsigned int dent_blocks)
6038c2ecf20Sopenharmony_ci{
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	unsigned int segno, left_blocks;
6068c2ecf20Sopenharmony_ci	int i;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	/* check current node segment */
6098c2ecf20Sopenharmony_ci	for (i = CURSEG_HOT_NODE; i <= CURSEG_COLD_NODE; i++) {
6108c2ecf20Sopenharmony_ci		segno = CURSEG_I(sbi, i)->segno;
6118c2ecf20Sopenharmony_ci		left_blocks = f2fs_usable_blks_in_seg(sbi, segno) -
6128c2ecf20Sopenharmony_ci				get_seg_entry(sbi, segno)->ckpt_valid_blocks;
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci		if (node_blocks > left_blocks)
6158c2ecf20Sopenharmony_ci			return false;
6168c2ecf20Sopenharmony_ci	}
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	/* check current data segment */
6198c2ecf20Sopenharmony_ci	segno = CURSEG_I(sbi, CURSEG_HOT_DATA)->segno;
6208c2ecf20Sopenharmony_ci	left_blocks = f2fs_usable_blks_in_seg(sbi, segno) -
6218c2ecf20Sopenharmony_ci			get_seg_entry(sbi, segno)->ckpt_valid_blocks;
6228c2ecf20Sopenharmony_ci	if (dent_blocks > left_blocks)
6238c2ecf20Sopenharmony_ci		return false;
6248c2ecf20Sopenharmony_ci	return true;
6258c2ecf20Sopenharmony_ci}
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_cistatic inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi,
6288c2ecf20Sopenharmony_ci					int freed, int needed)
6298c2ecf20Sopenharmony_ci{
6308c2ecf20Sopenharmony_ci	unsigned int total_node_blocks = get_pages(sbi, F2FS_DIRTY_NODES) +
6318c2ecf20Sopenharmony_ci					get_pages(sbi, F2FS_DIRTY_DENTS) +
6328c2ecf20Sopenharmony_ci					get_pages(sbi, F2FS_DIRTY_IMETA);
6338c2ecf20Sopenharmony_ci	unsigned int total_dent_blocks = get_pages(sbi, F2FS_DIRTY_DENTS);
6348c2ecf20Sopenharmony_ci	unsigned int node_secs = total_node_blocks / BLKS_PER_SEC(sbi);
6358c2ecf20Sopenharmony_ci	unsigned int dent_secs = total_dent_blocks / BLKS_PER_SEC(sbi);
6368c2ecf20Sopenharmony_ci	unsigned int node_blocks = total_node_blocks % BLKS_PER_SEC(sbi);
6378c2ecf20Sopenharmony_ci	unsigned int dent_blocks = total_dent_blocks % BLKS_PER_SEC(sbi);
6388c2ecf20Sopenharmony_ci	unsigned int free, need_lower, need_upper;
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
6418c2ecf20Sopenharmony_ci		return false;
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	free = free_sections(sbi) + freed;
6448c2ecf20Sopenharmony_ci	need_lower = node_secs + dent_secs + reserved_sections(sbi) + needed;
6458c2ecf20Sopenharmony_ci	need_upper = need_lower + (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0);
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	if (free > need_upper)
6488c2ecf20Sopenharmony_ci		return false;
6498c2ecf20Sopenharmony_ci	else if (free <= need_lower)
6508c2ecf20Sopenharmony_ci		return true;
6518c2ecf20Sopenharmony_ci	return !has_curseg_enough_space(sbi, node_blocks, dent_blocks);
6528c2ecf20Sopenharmony_ci}
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_cistatic inline bool f2fs_is_checkpoint_ready(struct f2fs_sb_info *sbi)
6558c2ecf20Sopenharmony_ci{
6568c2ecf20Sopenharmony_ci	if (likely(!is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
6578c2ecf20Sopenharmony_ci		return true;
6588c2ecf20Sopenharmony_ci	if (likely(!has_not_enough_free_secs(sbi, 0, 0)))
6598c2ecf20Sopenharmony_ci		return true;
6608c2ecf20Sopenharmony_ci	return false;
6618c2ecf20Sopenharmony_ci}
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_cistatic inline bool excess_prefree_segs(struct f2fs_sb_info *sbi)
6648c2ecf20Sopenharmony_ci{
6658c2ecf20Sopenharmony_ci	return prefree_segments(sbi) > SM_I(sbi)->rec_prefree_segments;
6668c2ecf20Sopenharmony_ci}
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_cistatic inline int utilization(struct f2fs_sb_info *sbi)
6698c2ecf20Sopenharmony_ci{
6708c2ecf20Sopenharmony_ci	return div_u64((u64)valid_user_blocks(sbi) * 100,
6718c2ecf20Sopenharmony_ci					sbi->user_block_count);
6728c2ecf20Sopenharmony_ci}
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci/*
6758c2ecf20Sopenharmony_ci * Sometimes f2fs may be better to drop out-of-place update policy.
6768c2ecf20Sopenharmony_ci * And, users can control the policy through sysfs entries.
6778c2ecf20Sopenharmony_ci * There are five policies with triggering conditions as follows.
6788c2ecf20Sopenharmony_ci * F2FS_IPU_FORCE - all the time,
6798c2ecf20Sopenharmony_ci * F2FS_IPU_SSR - if SSR mode is activated,
6808c2ecf20Sopenharmony_ci * F2FS_IPU_UTIL - if FS utilization is over threashold,
6818c2ecf20Sopenharmony_ci * F2FS_IPU_SSR_UTIL - if SSR mode is activated and FS utilization is over
6828c2ecf20Sopenharmony_ci *                     threashold,
6838c2ecf20Sopenharmony_ci * F2FS_IPU_FSYNC - activated in fsync path only for high performance flash
6848c2ecf20Sopenharmony_ci *                     storages. IPU will be triggered only if the # of dirty
6858c2ecf20Sopenharmony_ci *                     pages over min_fsync_blocks. (=default option)
6868c2ecf20Sopenharmony_ci * F2FS_IPU_ASYNC - do IPU given by asynchronous write requests.
6878c2ecf20Sopenharmony_ci * F2FS_IPU_NOCACHE - disable IPU bio cache.
6888c2ecf20Sopenharmony_ci * F2FS_IPUT_DISABLE - disable IPU. (=default option in LFS mode)
6898c2ecf20Sopenharmony_ci */
6908c2ecf20Sopenharmony_ci#define DEF_MIN_IPU_UTIL	70
6918c2ecf20Sopenharmony_ci#define DEF_MIN_FSYNC_BLOCKS	8
6928c2ecf20Sopenharmony_ci#define DEF_MIN_HOT_BLOCKS	16
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci#define SMALL_VOLUME_SEGMENTS	(16 * 512)	/* 16GB */
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_cienum {
6978c2ecf20Sopenharmony_ci	F2FS_IPU_FORCE,
6988c2ecf20Sopenharmony_ci	F2FS_IPU_SSR,
6998c2ecf20Sopenharmony_ci	F2FS_IPU_UTIL,
7008c2ecf20Sopenharmony_ci	F2FS_IPU_SSR_UTIL,
7018c2ecf20Sopenharmony_ci	F2FS_IPU_FSYNC,
7028c2ecf20Sopenharmony_ci	F2FS_IPU_ASYNC,
7038c2ecf20Sopenharmony_ci	F2FS_IPU_NOCACHE,
7048c2ecf20Sopenharmony_ci};
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_cistatic inline unsigned int curseg_segno(struct f2fs_sb_info *sbi,
7078c2ecf20Sopenharmony_ci		int type)
7088c2ecf20Sopenharmony_ci{
7098c2ecf20Sopenharmony_ci	struct curseg_info *curseg = CURSEG_I(sbi, type);
7108c2ecf20Sopenharmony_ci	return curseg->segno;
7118c2ecf20Sopenharmony_ci}
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_cistatic inline unsigned char curseg_alloc_type(struct f2fs_sb_info *sbi,
7148c2ecf20Sopenharmony_ci		int type)
7158c2ecf20Sopenharmony_ci{
7168c2ecf20Sopenharmony_ci	struct curseg_info *curseg = CURSEG_I(sbi, type);
7178c2ecf20Sopenharmony_ci	return curseg->alloc_type;
7188c2ecf20Sopenharmony_ci}
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_cistatic inline unsigned short curseg_blkoff(struct f2fs_sb_info *sbi, int type)
7218c2ecf20Sopenharmony_ci{
7228c2ecf20Sopenharmony_ci	struct curseg_info *curseg = CURSEG_I(sbi, type);
7238c2ecf20Sopenharmony_ci	return curseg->next_blkoff;
7248c2ecf20Sopenharmony_ci}
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_cistatic inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno)
7278c2ecf20Sopenharmony_ci{
7288c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, segno > TOTAL_SEGS(sbi) - 1);
7298c2ecf20Sopenharmony_ci}
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_cistatic inline void verify_fio_blkaddr(struct f2fs_io_info *fio)
7328c2ecf20Sopenharmony_ci{
7338c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = fio->sbi;
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	if (__is_valid_data_blkaddr(fio->old_blkaddr))
7368c2ecf20Sopenharmony_ci		verify_blkaddr(sbi, fio->old_blkaddr, __is_meta_io(fio) ?
7378c2ecf20Sopenharmony_ci					META_GENERIC : DATA_GENERIC);
7388c2ecf20Sopenharmony_ci	verify_blkaddr(sbi, fio->new_blkaddr, __is_meta_io(fio) ?
7398c2ecf20Sopenharmony_ci					META_GENERIC : DATA_GENERIC_ENHANCE);
7408c2ecf20Sopenharmony_ci}
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci/*
7438c2ecf20Sopenharmony_ci * Summary block is always treated as an invalid block
7448c2ecf20Sopenharmony_ci */
7458c2ecf20Sopenharmony_cistatic inline int check_block_count(struct f2fs_sb_info *sbi,
7468c2ecf20Sopenharmony_ci		int segno, struct f2fs_sit_entry *raw_sit)
7478c2ecf20Sopenharmony_ci{
7488c2ecf20Sopenharmony_ci	bool is_valid  = test_bit_le(0, raw_sit->valid_map) ? true : false;
7498c2ecf20Sopenharmony_ci	int valid_blocks = 0;
7508c2ecf20Sopenharmony_ci	int cur_pos = 0, next_pos;
7518c2ecf20Sopenharmony_ci	unsigned int usable_blks_per_seg = f2fs_usable_blks_in_seg(sbi, segno);
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	/* check bitmap with valid block count */
7548c2ecf20Sopenharmony_ci	do {
7558c2ecf20Sopenharmony_ci		if (is_valid) {
7568c2ecf20Sopenharmony_ci			next_pos = find_next_zero_bit_le(&raw_sit->valid_map,
7578c2ecf20Sopenharmony_ci					usable_blks_per_seg,
7588c2ecf20Sopenharmony_ci					cur_pos);
7598c2ecf20Sopenharmony_ci			valid_blocks += next_pos - cur_pos;
7608c2ecf20Sopenharmony_ci		} else
7618c2ecf20Sopenharmony_ci			next_pos = find_next_bit_le(&raw_sit->valid_map,
7628c2ecf20Sopenharmony_ci					usable_blks_per_seg,
7638c2ecf20Sopenharmony_ci					cur_pos);
7648c2ecf20Sopenharmony_ci		cur_pos = next_pos;
7658c2ecf20Sopenharmony_ci		is_valid = !is_valid;
7668c2ecf20Sopenharmony_ci	} while (cur_pos < usable_blks_per_seg);
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	if (unlikely(GET_SIT_VBLOCKS(raw_sit) != valid_blocks)) {
7698c2ecf20Sopenharmony_ci		f2fs_err(sbi, "Mismatch valid blocks %d vs. %d",
7708c2ecf20Sopenharmony_ci			 GET_SIT_VBLOCKS(raw_sit), valid_blocks);
7718c2ecf20Sopenharmony_ci		set_sbi_flag(sbi, SBI_NEED_FSCK);
7728c2ecf20Sopenharmony_ci		return -EFSCORRUPTED;
7738c2ecf20Sopenharmony_ci	}
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	if (usable_blks_per_seg < sbi->blocks_per_seg)
7768c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, find_next_bit_le(&raw_sit->valid_map,
7778c2ecf20Sopenharmony_ci				sbi->blocks_per_seg,
7788c2ecf20Sopenharmony_ci				usable_blks_per_seg) != sbi->blocks_per_seg);
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	/* check segment usage, and check boundary of a given segment number */
7818c2ecf20Sopenharmony_ci	if (unlikely(GET_SIT_VBLOCKS(raw_sit) > usable_blks_per_seg
7828c2ecf20Sopenharmony_ci					|| segno > TOTAL_SEGS(sbi) - 1)) {
7838c2ecf20Sopenharmony_ci		f2fs_err(sbi, "Wrong valid blocks %d or segno %u",
7848c2ecf20Sopenharmony_ci			 GET_SIT_VBLOCKS(raw_sit), segno);
7858c2ecf20Sopenharmony_ci		set_sbi_flag(sbi, SBI_NEED_FSCK);
7868c2ecf20Sopenharmony_ci		return -EFSCORRUPTED;
7878c2ecf20Sopenharmony_ci	}
7888c2ecf20Sopenharmony_ci	return 0;
7898c2ecf20Sopenharmony_ci}
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_cistatic inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi,
7928c2ecf20Sopenharmony_ci						unsigned int start)
7938c2ecf20Sopenharmony_ci{
7948c2ecf20Sopenharmony_ci	struct sit_info *sit_i = SIT_I(sbi);
7958c2ecf20Sopenharmony_ci	unsigned int offset = SIT_BLOCK_OFFSET(start);
7968c2ecf20Sopenharmony_ci	block_t blk_addr = sit_i->sit_base_addr + offset;
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	check_seg_range(sbi, start);
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
8018c2ecf20Sopenharmony_ci	if (f2fs_test_bit(offset, sit_i->sit_bitmap) !=
8028c2ecf20Sopenharmony_ci			f2fs_test_bit(offset, sit_i->sit_bitmap_mir))
8038c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, 1);
8048c2ecf20Sopenharmony_ci#endif
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	/* calculate sit block address */
8078c2ecf20Sopenharmony_ci	if (f2fs_test_bit(offset, sit_i->sit_bitmap))
8088c2ecf20Sopenharmony_ci		blk_addr += sit_i->sit_blocks;
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci	return blk_addr;
8118c2ecf20Sopenharmony_ci}
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_cistatic inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi,
8148c2ecf20Sopenharmony_ci						pgoff_t block_addr)
8158c2ecf20Sopenharmony_ci{
8168c2ecf20Sopenharmony_ci	struct sit_info *sit_i = SIT_I(sbi);
8178c2ecf20Sopenharmony_ci	block_addr -= sit_i->sit_base_addr;
8188c2ecf20Sopenharmony_ci	if (block_addr < sit_i->sit_blocks)
8198c2ecf20Sopenharmony_ci		block_addr += sit_i->sit_blocks;
8208c2ecf20Sopenharmony_ci	else
8218c2ecf20Sopenharmony_ci		block_addr -= sit_i->sit_blocks;
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	return block_addr + sit_i->sit_base_addr;
8248c2ecf20Sopenharmony_ci}
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_cistatic inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start)
8278c2ecf20Sopenharmony_ci{
8288c2ecf20Sopenharmony_ci	unsigned int block_off = SIT_BLOCK_OFFSET(start);
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	f2fs_change_bit(block_off, sit_i->sit_bitmap);
8318c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
8328c2ecf20Sopenharmony_ci	f2fs_change_bit(block_off, sit_i->sit_bitmap_mir);
8338c2ecf20Sopenharmony_ci#endif
8348c2ecf20Sopenharmony_ci}
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_cistatic inline unsigned long long get_mtime(struct f2fs_sb_info *sbi,
8378c2ecf20Sopenharmony_ci						bool base_time)
8388c2ecf20Sopenharmony_ci{
8398c2ecf20Sopenharmony_ci	struct sit_info *sit_i = SIT_I(sbi);
8408c2ecf20Sopenharmony_ci	time64_t diff, now = ktime_get_boottime_seconds();
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	if (now >= sit_i->mounted_time)
8438c2ecf20Sopenharmony_ci		return sit_i->elapsed_time + now - sit_i->mounted_time;
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci	/* system time is set to the past */
8468c2ecf20Sopenharmony_ci	if (!base_time) {
8478c2ecf20Sopenharmony_ci		diff = sit_i->mounted_time - now;
8488c2ecf20Sopenharmony_ci		if (sit_i->elapsed_time >= diff)
8498c2ecf20Sopenharmony_ci			return sit_i->elapsed_time - diff;
8508c2ecf20Sopenharmony_ci		return 0;
8518c2ecf20Sopenharmony_ci	}
8528c2ecf20Sopenharmony_ci	return sit_i->elapsed_time;
8538c2ecf20Sopenharmony_ci}
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_cistatic inline void set_summary(struct f2fs_summary *sum, nid_t nid,
8568c2ecf20Sopenharmony_ci			unsigned int ofs_in_node, unsigned char version)
8578c2ecf20Sopenharmony_ci{
8588c2ecf20Sopenharmony_ci	sum->nid = cpu_to_le32(nid);
8598c2ecf20Sopenharmony_ci	sum->ofs_in_node = cpu_to_le16(ofs_in_node);
8608c2ecf20Sopenharmony_ci	sum->version = version;
8618c2ecf20Sopenharmony_ci}
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_cistatic inline block_t start_sum_block(struct f2fs_sb_info *sbi)
8648c2ecf20Sopenharmony_ci{
8658c2ecf20Sopenharmony_ci	return __start_cp_addr(sbi) +
8668c2ecf20Sopenharmony_ci		le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
8678c2ecf20Sopenharmony_ci}
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_cistatic inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
8708c2ecf20Sopenharmony_ci{
8718c2ecf20Sopenharmony_ci	return __start_cp_addr(sbi) +
8728c2ecf20Sopenharmony_ci		le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_total_block_count)
8738c2ecf20Sopenharmony_ci				- (base + 1) + type;
8748c2ecf20Sopenharmony_ci}
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_cistatic inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int secno)
8778c2ecf20Sopenharmony_ci{
8788c2ecf20Sopenharmony_ci	if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec == secno))
8798c2ecf20Sopenharmony_ci		return true;
8808c2ecf20Sopenharmony_ci	return false;
8818c2ecf20Sopenharmony_ci}
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci/*
8848c2ecf20Sopenharmony_ci * It is very important to gather dirty pages and write at once, so that we can
8858c2ecf20Sopenharmony_ci * submit a big bio without interfering other data writes.
8868c2ecf20Sopenharmony_ci * By default, 512 pages for directory data,
8878c2ecf20Sopenharmony_ci * 512 pages (2MB) * 8 for nodes, and
8888c2ecf20Sopenharmony_ci * 256 pages * 8 for meta are set.
8898c2ecf20Sopenharmony_ci */
8908c2ecf20Sopenharmony_cistatic inline int nr_pages_to_skip(struct f2fs_sb_info *sbi, int type)
8918c2ecf20Sopenharmony_ci{
8928c2ecf20Sopenharmony_ci	if (sbi->sb->s_bdi->wb.dirty_exceeded)
8938c2ecf20Sopenharmony_ci		return 0;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	if (type == DATA)
8968c2ecf20Sopenharmony_ci		return sbi->blocks_per_seg;
8978c2ecf20Sopenharmony_ci	else if (type == NODE)
8988c2ecf20Sopenharmony_ci		return 8 * sbi->blocks_per_seg;
8998c2ecf20Sopenharmony_ci	else if (type == META)
9008c2ecf20Sopenharmony_ci		return 8 * BIO_MAX_PAGES;
9018c2ecf20Sopenharmony_ci	else
9028c2ecf20Sopenharmony_ci		return 0;
9038c2ecf20Sopenharmony_ci}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci/*
9068c2ecf20Sopenharmony_ci * When writing pages, it'd better align nr_to_write for segment size.
9078c2ecf20Sopenharmony_ci */
9088c2ecf20Sopenharmony_cistatic inline long nr_pages_to_write(struct f2fs_sb_info *sbi, int type,
9098c2ecf20Sopenharmony_ci					struct writeback_control *wbc)
9108c2ecf20Sopenharmony_ci{
9118c2ecf20Sopenharmony_ci	long nr_to_write, desired;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	if (wbc->sync_mode != WB_SYNC_NONE)
9148c2ecf20Sopenharmony_ci		return 0;
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci	nr_to_write = wbc->nr_to_write;
9178c2ecf20Sopenharmony_ci	desired = BIO_MAX_PAGES;
9188c2ecf20Sopenharmony_ci	if (type == NODE)
9198c2ecf20Sopenharmony_ci		desired <<= 1;
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci	wbc->nr_to_write = desired;
9228c2ecf20Sopenharmony_ci	return desired - nr_to_write;
9238c2ecf20Sopenharmony_ci}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_cistatic inline void wake_up_discard_thread(struct f2fs_sb_info *sbi, bool force)
9268c2ecf20Sopenharmony_ci{
9278c2ecf20Sopenharmony_ci	struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
9288c2ecf20Sopenharmony_ci	bool wakeup = false;
9298c2ecf20Sopenharmony_ci	int i;
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	if (force)
9328c2ecf20Sopenharmony_ci		goto wake_up;
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	mutex_lock(&dcc->cmd_lock);
9358c2ecf20Sopenharmony_ci	for (i = MAX_PLIST_NUM - 1; i >= 0; i--) {
9368c2ecf20Sopenharmony_ci		if (i + 1 < dcc->discard_granularity)
9378c2ecf20Sopenharmony_ci			break;
9388c2ecf20Sopenharmony_ci		if (!list_empty(&dcc->pend_list[i])) {
9398c2ecf20Sopenharmony_ci			wakeup = true;
9408c2ecf20Sopenharmony_ci			break;
9418c2ecf20Sopenharmony_ci		}
9428c2ecf20Sopenharmony_ci	}
9438c2ecf20Sopenharmony_ci	mutex_unlock(&dcc->cmd_lock);
9448c2ecf20Sopenharmony_ci	if (!wakeup || !is_idle(sbi, DISCARD_TIME))
9458c2ecf20Sopenharmony_ci		return;
9468c2ecf20Sopenharmony_ciwake_up:
9478c2ecf20Sopenharmony_ci	dcc->discard_wake = 1;
9488c2ecf20Sopenharmony_ci	wake_up_interruptible_all(&dcc->discard_wait_queue);
9498c2ecf20Sopenharmony_ci}
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_GRADING_SSR
9528c2ecf20Sopenharmony_cistatic inline int check_io_seq(int blks)
9538c2ecf20Sopenharmony_ci{
9548c2ecf20Sopenharmony_ci	if (blks >= SSR_CONTIG_LARGE)
9558c2ecf20Sopenharmony_ci		return SEQ_256BLKS;
9568c2ecf20Sopenharmony_ci	if (blks >= SSR_CONTIG_DIRTY_NUMS)
9578c2ecf20Sopenharmony_ci		return SEQ_32BLKS;
9588c2ecf20Sopenharmony_ci	return SEQ_NONE;
9598c2ecf20Sopenharmony_ci}
9608c2ecf20Sopenharmony_ci#endif
961