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