162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/f2fs/node.h 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd. 662306a36Sopenharmony_ci * http://www.samsung.com/ 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci/* start node id of a node block dedicated to the given node id */ 962306a36Sopenharmony_ci#define START_NID(nid) (((nid) / NAT_ENTRY_PER_BLOCK) * NAT_ENTRY_PER_BLOCK) 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* node block offset on the NAT area dedicated to the given start node id */ 1262306a36Sopenharmony_ci#define NAT_BLOCK_OFFSET(start_nid) ((start_nid) / NAT_ENTRY_PER_BLOCK) 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* # of pages to perform synchronous readahead before building free nids */ 1562306a36Sopenharmony_ci#define FREE_NID_PAGES 8 1662306a36Sopenharmony_ci#define MAX_FREE_NIDS (NAT_ENTRY_PER_BLOCK * FREE_NID_PAGES) 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* size of free nid batch when shrinking */ 1962306a36Sopenharmony_ci#define SHRINK_NID_BATCH_SIZE 8 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define DEF_RA_NID_PAGES 0 /* # of nid pages to be readaheaded */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* maximum readahead size for node during getting data blocks */ 2462306a36Sopenharmony_ci#define MAX_RA_NODE 128 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* control the memory footprint threshold (10MB per 1GB ram) */ 2762306a36Sopenharmony_ci#define DEF_RAM_THRESHOLD 1 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* control dirty nats ratio threshold (default: 10% over max nid count) */ 3062306a36Sopenharmony_ci#define DEF_DIRTY_NAT_RATIO_THRESHOLD 10 3162306a36Sopenharmony_ci/* control total # of nats */ 3262306a36Sopenharmony_ci#define DEF_NAT_CACHE_THRESHOLD 100000 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* control total # of node writes used for roll-fowrad recovery */ 3562306a36Sopenharmony_ci#define DEF_RF_NODE_BLOCKS 0 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* vector size for gang look-up from nat cache that consists of radix tree */ 3862306a36Sopenharmony_ci#define NAT_VEC_SIZE 32 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* return value for read_node_page */ 4162306a36Sopenharmony_ci#define LOCKED_PAGE 1 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* check pinned file's alignment status of physical blocks */ 4462306a36Sopenharmony_ci#define FILE_NOT_ALIGNED 1 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* For flag in struct node_info */ 4762306a36Sopenharmony_cienum { 4862306a36Sopenharmony_ci IS_CHECKPOINTED, /* is it checkpointed before? */ 4962306a36Sopenharmony_ci HAS_FSYNCED_INODE, /* is the inode fsynced before? */ 5062306a36Sopenharmony_ci HAS_LAST_FSYNC, /* has the latest node fsync mark? */ 5162306a36Sopenharmony_ci IS_DIRTY, /* this nat entry is dirty? */ 5262306a36Sopenharmony_ci IS_PREALLOC, /* nat entry is preallocated */ 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* 5662306a36Sopenharmony_ci * For node information 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_cistruct node_info { 5962306a36Sopenharmony_ci nid_t nid; /* node id */ 6062306a36Sopenharmony_ci nid_t ino; /* inode number of the node's owner */ 6162306a36Sopenharmony_ci block_t blk_addr; /* block address of the node */ 6262306a36Sopenharmony_ci unsigned char version; /* version of the node */ 6362306a36Sopenharmony_ci unsigned char flag; /* for node information bits */ 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistruct nat_entry { 6762306a36Sopenharmony_ci struct list_head list; /* for clean or dirty nat list */ 6862306a36Sopenharmony_ci struct node_info ni; /* in-memory node information */ 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define nat_get_nid(nat) ((nat)->ni.nid) 7262306a36Sopenharmony_ci#define nat_set_nid(nat, n) ((nat)->ni.nid = (n)) 7362306a36Sopenharmony_ci#define nat_get_blkaddr(nat) ((nat)->ni.blk_addr) 7462306a36Sopenharmony_ci#define nat_set_blkaddr(nat, b) ((nat)->ni.blk_addr = (b)) 7562306a36Sopenharmony_ci#define nat_get_ino(nat) ((nat)->ni.ino) 7662306a36Sopenharmony_ci#define nat_set_ino(nat, i) ((nat)->ni.ino = (i)) 7762306a36Sopenharmony_ci#define nat_get_version(nat) ((nat)->ni.version) 7862306a36Sopenharmony_ci#define nat_set_version(nat, v) ((nat)->ni.version = (v)) 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#define inc_node_version(version) (++(version)) 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic inline void copy_node_info(struct node_info *dst, 8362306a36Sopenharmony_ci struct node_info *src) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci dst->nid = src->nid; 8662306a36Sopenharmony_ci dst->ino = src->ino; 8762306a36Sopenharmony_ci dst->blk_addr = src->blk_addr; 8862306a36Sopenharmony_ci dst->version = src->version; 8962306a36Sopenharmony_ci /* should not copy flag here */ 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic inline void set_nat_flag(struct nat_entry *ne, 9362306a36Sopenharmony_ci unsigned int type, bool set) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci if (set) 9662306a36Sopenharmony_ci ne->ni.flag |= BIT(type); 9762306a36Sopenharmony_ci else 9862306a36Sopenharmony_ci ne->ni.flag &= ~BIT(type); 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic inline bool get_nat_flag(struct nat_entry *ne, unsigned int type) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci return ne->ni.flag & BIT(type); 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic inline void nat_reset_flag(struct nat_entry *ne) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci /* these states can be set only after checkpoint was done */ 10962306a36Sopenharmony_ci set_nat_flag(ne, IS_CHECKPOINTED, true); 11062306a36Sopenharmony_ci set_nat_flag(ne, HAS_FSYNCED_INODE, false); 11162306a36Sopenharmony_ci set_nat_flag(ne, HAS_LAST_FSYNC, true); 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic inline void node_info_from_raw_nat(struct node_info *ni, 11562306a36Sopenharmony_ci struct f2fs_nat_entry *raw_ne) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci ni->ino = le32_to_cpu(raw_ne->ino); 11862306a36Sopenharmony_ci ni->blk_addr = le32_to_cpu(raw_ne->block_addr); 11962306a36Sopenharmony_ci ni->version = raw_ne->version; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic inline void raw_nat_from_node_info(struct f2fs_nat_entry *raw_ne, 12362306a36Sopenharmony_ci struct node_info *ni) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci raw_ne->ino = cpu_to_le32(ni->ino); 12662306a36Sopenharmony_ci raw_ne->block_addr = cpu_to_le32(ni->blk_addr); 12762306a36Sopenharmony_ci raw_ne->version = ni->version; 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic inline bool excess_dirty_nats(struct f2fs_sb_info *sbi) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci return NM_I(sbi)->nat_cnt[DIRTY_NAT] >= NM_I(sbi)->max_nid * 13362306a36Sopenharmony_ci NM_I(sbi)->dirty_nats_ratio / 100; 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic inline bool excess_cached_nats(struct f2fs_sb_info *sbi) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci return NM_I(sbi)->nat_cnt[TOTAL_NAT] >= DEF_NAT_CACHE_THRESHOLD; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cienum mem_type { 14262306a36Sopenharmony_ci FREE_NIDS, /* indicates the free nid list */ 14362306a36Sopenharmony_ci NAT_ENTRIES, /* indicates the cached nat entry */ 14462306a36Sopenharmony_ci DIRTY_DENTS, /* indicates dirty dentry pages */ 14562306a36Sopenharmony_ci INO_ENTRIES, /* indicates inode entries */ 14662306a36Sopenharmony_ci READ_EXTENT_CACHE, /* indicates read extent cache */ 14762306a36Sopenharmony_ci AGE_EXTENT_CACHE, /* indicates age extent cache */ 14862306a36Sopenharmony_ci DISCARD_CACHE, /* indicates memory of cached discard cmds */ 14962306a36Sopenharmony_ci COMPRESS_PAGE, /* indicates memory of cached compressed pages */ 15062306a36Sopenharmony_ci BASE_CHECK, /* check kernel status */ 15162306a36Sopenharmony_ci}; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistruct nat_entry_set { 15462306a36Sopenharmony_ci struct list_head set_list; /* link with other nat sets */ 15562306a36Sopenharmony_ci struct list_head entry_list; /* link with dirty nat entries */ 15662306a36Sopenharmony_ci nid_t set; /* set number*/ 15762306a36Sopenharmony_ci unsigned int entry_cnt; /* the # of nat entries in set */ 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistruct free_nid { 16162306a36Sopenharmony_ci struct list_head list; /* for free node id list */ 16262306a36Sopenharmony_ci nid_t nid; /* node id */ 16362306a36Sopenharmony_ci int state; /* in use or not: FREE_NID or PREALLOC_NID */ 16462306a36Sopenharmony_ci}; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cistatic inline void next_free_nid(struct f2fs_sb_info *sbi, nid_t *nid) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 16962306a36Sopenharmony_ci struct free_nid *fnid; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 17262306a36Sopenharmony_ci if (nm_i->nid_cnt[FREE_NID] <= 0) { 17362306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 17462306a36Sopenharmony_ci return; 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci fnid = list_first_entry(&nm_i->free_nid_list, struct free_nid, list); 17762306a36Sopenharmony_ci *nid = fnid->nid; 17862306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci/* 18262306a36Sopenharmony_ci * inline functions 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_cistatic inline void get_nat_bitmap(struct f2fs_sb_info *sbi, void *addr) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS 18962306a36Sopenharmony_ci if (memcmp(nm_i->nat_bitmap, nm_i->nat_bitmap_mir, 19062306a36Sopenharmony_ci nm_i->bitmap_size)) 19162306a36Sopenharmony_ci f2fs_bug_on(sbi, 1); 19262306a36Sopenharmony_ci#endif 19362306a36Sopenharmony_ci memcpy(addr, nm_i->nat_bitmap, nm_i->bitmap_size); 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic inline pgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 19962306a36Sopenharmony_ci pgoff_t block_off; 20062306a36Sopenharmony_ci pgoff_t block_addr; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci /* 20362306a36Sopenharmony_ci * block_off = segment_off * 512 + off_in_segment 20462306a36Sopenharmony_ci * OLD = (segment_off * 512) * 2 + off_in_segment 20562306a36Sopenharmony_ci * NEW = 2 * (segment_off * 512 + off_in_segment) - off_in_segment 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_ci block_off = NAT_BLOCK_OFFSET(start); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci block_addr = (pgoff_t)(nm_i->nat_blkaddr + 21062306a36Sopenharmony_ci (block_off << 1) - 21162306a36Sopenharmony_ci (block_off & (sbi->blocks_per_seg - 1))); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci if (f2fs_test_bit(block_off, nm_i->nat_bitmap)) 21462306a36Sopenharmony_ci block_addr += sbi->blocks_per_seg; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci return block_addr; 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi, 22062306a36Sopenharmony_ci pgoff_t block_addr) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci block_addr -= nm_i->nat_blkaddr; 22562306a36Sopenharmony_ci block_addr ^= BIT(sbi->log_blocks_per_seg); 22662306a36Sopenharmony_ci return block_addr + nm_i->nat_blkaddr; 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci unsigned int block_off = NAT_BLOCK_OFFSET(start_nid); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci f2fs_change_bit(block_off, nm_i->nat_bitmap); 23462306a36Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS 23562306a36Sopenharmony_ci f2fs_change_bit(block_off, nm_i->nat_bitmap_mir); 23662306a36Sopenharmony_ci#endif 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic inline nid_t ino_of_node(struct page *node_page) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(node_page); 24262306a36Sopenharmony_ci return le32_to_cpu(rn->footer.ino); 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic inline nid_t nid_of_node(struct page *node_page) 24662306a36Sopenharmony_ci{ 24762306a36Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(node_page); 24862306a36Sopenharmony_ci return le32_to_cpu(rn->footer.nid); 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic inline unsigned int ofs_of_node(struct page *node_page) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(node_page); 25462306a36Sopenharmony_ci unsigned flag = le32_to_cpu(rn->footer.flag); 25562306a36Sopenharmony_ci return flag >> OFFSET_BIT_SHIFT; 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic inline __u64 cpver_of_node(struct page *node_page) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(node_page); 26162306a36Sopenharmony_ci return le64_to_cpu(rn->footer.cp_ver); 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic inline block_t next_blkaddr_of_node(struct page *node_page) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(node_page); 26762306a36Sopenharmony_ci return le32_to_cpu(rn->footer.next_blkaddr); 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic inline void fill_node_footer(struct page *page, nid_t nid, 27162306a36Sopenharmony_ci nid_t ino, unsigned int ofs, bool reset) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(page); 27462306a36Sopenharmony_ci unsigned int old_flag = 0; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci if (reset) 27762306a36Sopenharmony_ci memset(rn, 0, sizeof(*rn)); 27862306a36Sopenharmony_ci else 27962306a36Sopenharmony_ci old_flag = le32_to_cpu(rn->footer.flag); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci rn->footer.nid = cpu_to_le32(nid); 28262306a36Sopenharmony_ci rn->footer.ino = cpu_to_le32(ino); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci /* should remain old flag bits such as COLD_BIT_SHIFT */ 28562306a36Sopenharmony_ci rn->footer.flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) | 28662306a36Sopenharmony_ci (old_flag & OFFSET_BIT_MASK)); 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic inline void copy_node_footer(struct page *dst, struct page *src) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci struct f2fs_node *src_rn = F2FS_NODE(src); 29262306a36Sopenharmony_ci struct f2fs_node *dst_rn = F2FS_NODE(dst); 29362306a36Sopenharmony_ci memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer)); 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_cistatic inline void fill_node_footer_blkaddr(struct page *page, block_t blkaddr) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_P_SB(page)); 29962306a36Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(page); 30062306a36Sopenharmony_ci __u64 cp_ver = cur_cp_version(ckpt); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG)) 30362306a36Sopenharmony_ci cp_ver |= (cur_cp_crc(ckpt) << 32); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci rn->footer.cp_ver = cpu_to_le64(cp_ver); 30662306a36Sopenharmony_ci rn->footer.next_blkaddr = cpu_to_le32(blkaddr); 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistatic inline bool is_recoverable_dnode(struct page *page) 31062306a36Sopenharmony_ci{ 31162306a36Sopenharmony_ci struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_P_SB(page)); 31262306a36Sopenharmony_ci __u64 cp_ver = cur_cp_version(ckpt); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci /* Don't care crc part, if fsck.f2fs sets it. */ 31562306a36Sopenharmony_ci if (__is_set_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG)) 31662306a36Sopenharmony_ci return (cp_ver << 32) == (cpver_of_node(page) << 32); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG)) 31962306a36Sopenharmony_ci cp_ver |= (cur_cp_crc(ckpt) << 32); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci return cp_ver == cpver_of_node(page); 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci/* 32562306a36Sopenharmony_ci * f2fs assigns the following node offsets described as (num). 32662306a36Sopenharmony_ci * N = NIDS_PER_BLOCK 32762306a36Sopenharmony_ci * 32862306a36Sopenharmony_ci * Inode block (0) 32962306a36Sopenharmony_ci * |- direct node (1) 33062306a36Sopenharmony_ci * |- direct node (2) 33162306a36Sopenharmony_ci * |- indirect node (3) 33262306a36Sopenharmony_ci * | `- direct node (4 => 4 + N - 1) 33362306a36Sopenharmony_ci * |- indirect node (4 + N) 33462306a36Sopenharmony_ci * | `- direct node (5 + N => 5 + 2N - 1) 33562306a36Sopenharmony_ci * `- double indirect node (5 + 2N) 33662306a36Sopenharmony_ci * `- indirect node (6 + 2N) 33762306a36Sopenharmony_ci * `- direct node 33862306a36Sopenharmony_ci * ...... 33962306a36Sopenharmony_ci * `- indirect node ((6 + 2N) + x(N + 1)) 34062306a36Sopenharmony_ci * `- direct node 34162306a36Sopenharmony_ci * ...... 34262306a36Sopenharmony_ci * `- indirect node ((6 + 2N) + (N - 1)(N + 1)) 34362306a36Sopenharmony_ci * `- direct node 34462306a36Sopenharmony_ci */ 34562306a36Sopenharmony_cistatic inline bool IS_DNODE(struct page *node_page) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci unsigned int ofs = ofs_of_node(node_page); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (f2fs_has_xattr_block(ofs)) 35062306a36Sopenharmony_ci return true; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK || 35362306a36Sopenharmony_ci ofs == 5 + 2 * NIDS_PER_BLOCK) 35462306a36Sopenharmony_ci return false; 35562306a36Sopenharmony_ci if (ofs >= 6 + 2 * NIDS_PER_BLOCK) { 35662306a36Sopenharmony_ci ofs -= 6 + 2 * NIDS_PER_BLOCK; 35762306a36Sopenharmony_ci if (!((long int)ofs % (NIDS_PER_BLOCK + 1))) 35862306a36Sopenharmony_ci return false; 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci return true; 36162306a36Sopenharmony_ci} 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_cistatic inline int set_nid(struct page *p, int off, nid_t nid, bool i) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(p); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci f2fs_wait_on_page_writeback(p, NODE, true, true); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if (i) 37062306a36Sopenharmony_ci rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid); 37162306a36Sopenharmony_ci else 37262306a36Sopenharmony_ci rn->in.nid[off] = cpu_to_le32(nid); 37362306a36Sopenharmony_ci return set_page_dirty(p); 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic inline nid_t get_nid(struct page *p, int off, bool i) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(p); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci if (i) 38162306a36Sopenharmony_ci return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]); 38262306a36Sopenharmony_ci return le32_to_cpu(rn->in.nid[off]); 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci/* 38662306a36Sopenharmony_ci * Coldness identification: 38762306a36Sopenharmony_ci * - Mark cold files in f2fs_inode_info 38862306a36Sopenharmony_ci * - Mark cold node blocks in their node footer 38962306a36Sopenharmony_ci * - Mark cold data pages in page cache 39062306a36Sopenharmony_ci */ 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic inline int is_node(struct page *page, int type) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(page); 39562306a36Sopenharmony_ci return le32_to_cpu(rn->footer.flag) & BIT(type); 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci#define is_cold_node(page) is_node(page, COLD_BIT_SHIFT) 39962306a36Sopenharmony_ci#define is_fsync_dnode(page) is_node(page, FSYNC_BIT_SHIFT) 40062306a36Sopenharmony_ci#define is_dent_dnode(page) is_node(page, DENT_BIT_SHIFT) 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic inline void set_cold_node(struct page *page, bool is_dir) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(page); 40562306a36Sopenharmony_ci unsigned int flag = le32_to_cpu(rn->footer.flag); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci if (is_dir) 40862306a36Sopenharmony_ci flag &= ~BIT(COLD_BIT_SHIFT); 40962306a36Sopenharmony_ci else 41062306a36Sopenharmony_ci flag |= BIT(COLD_BIT_SHIFT); 41162306a36Sopenharmony_ci rn->footer.flag = cpu_to_le32(flag); 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_cistatic inline void set_mark(struct page *page, int mark, int type) 41562306a36Sopenharmony_ci{ 41662306a36Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(page); 41762306a36Sopenharmony_ci unsigned int flag = le32_to_cpu(rn->footer.flag); 41862306a36Sopenharmony_ci if (mark) 41962306a36Sopenharmony_ci flag |= BIT(type); 42062306a36Sopenharmony_ci else 42162306a36Sopenharmony_ci flag &= ~BIT(type); 42262306a36Sopenharmony_ci rn->footer.flag = cpu_to_le32(flag); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS 42562306a36Sopenharmony_ci f2fs_inode_chksum_set(F2FS_P_SB(page), page); 42662306a36Sopenharmony_ci#endif 42762306a36Sopenharmony_ci} 42862306a36Sopenharmony_ci#define set_dentry_mark(page, mark) set_mark(page, mark, DENT_BIT_SHIFT) 42962306a36Sopenharmony_ci#define set_fsync_mark(page, mark) set_mark(page, mark, FSYNC_BIT_SHIFT) 430