15e5c12b0Sopenharmony_ci/** 25e5c12b0Sopenharmony_ci * node.h 35e5c12b0Sopenharmony_ci * 45e5c12b0Sopenharmony_ci * Many parts of codes are copied from Linux kernel/fs/f2fs. 55e5c12b0Sopenharmony_ci * 65e5c12b0Sopenharmony_ci * Copyright (C) 2015 Huawei Ltd. 75e5c12b0Sopenharmony_ci * Witten by: 85e5c12b0Sopenharmony_ci * Hou Pengyang <houpengyang@huawei.com> 95e5c12b0Sopenharmony_ci * Liu Shuoran <liushuoran@huawei.com> 105e5c12b0Sopenharmony_ci * Jaegeuk Kim <jaegeuk@kernel.org> 115e5c12b0Sopenharmony_ci * 125e5c12b0Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 135e5c12b0Sopenharmony_ci * it under the terms of the GNU General Public License version 2 as 145e5c12b0Sopenharmony_ci * published by the Free Software Foundation. 155e5c12b0Sopenharmony_ci */ 165e5c12b0Sopenharmony_ci#ifndef _NODE_H_ 175e5c12b0Sopenharmony_ci#define _NODE_H_ 185e5c12b0Sopenharmony_ci 195e5c12b0Sopenharmony_ci#include "fsck.h" 205e5c12b0Sopenharmony_ci 215e5c12b0Sopenharmony_cistatic inline int IS_INODE(struct f2fs_node *node) 225e5c12b0Sopenharmony_ci{ 235e5c12b0Sopenharmony_ci return ((node)->footer.nid == (node)->footer.ino); 245e5c12b0Sopenharmony_ci} 255e5c12b0Sopenharmony_ci 265e5c12b0Sopenharmony_cistatic inline unsigned int ADDRS_PER_PAGE(struct f2fs_sb_info *sbi, 275e5c12b0Sopenharmony_ci struct f2fs_node *node_blk, struct f2fs_node *inode_blk) 285e5c12b0Sopenharmony_ci{ 295e5c12b0Sopenharmony_ci nid_t ino = le32_to_cpu(node_blk->footer.ino); 305e5c12b0Sopenharmony_ci unsigned int nblocks; 315e5c12b0Sopenharmony_ci 325e5c12b0Sopenharmony_ci if (IS_INODE(node_blk)) 335e5c12b0Sopenharmony_ci return ADDRS_PER_INODE(&node_blk->i); 345e5c12b0Sopenharmony_ci 355e5c12b0Sopenharmony_ci if (!inode_blk) { 365e5c12b0Sopenharmony_ci struct node_info ni; 375e5c12b0Sopenharmony_ci 385e5c12b0Sopenharmony_ci inode_blk = calloc(BLOCK_SZ, 2); 395e5c12b0Sopenharmony_ci ASSERT(inode_blk); 405e5c12b0Sopenharmony_ci 415e5c12b0Sopenharmony_ci get_node_info(sbi, ino, &ni); 425e5c12b0Sopenharmony_ci ASSERT(dev_read_block(inode_blk, ni.blk_addr) >= 0); 435e5c12b0Sopenharmony_ci nblocks = ADDRS_PER_BLOCK(&inode_blk->i); 445e5c12b0Sopenharmony_ci free(inode_blk); 455e5c12b0Sopenharmony_ci } else { 465e5c12b0Sopenharmony_ci nblocks = ADDRS_PER_BLOCK(&inode_blk->i); 475e5c12b0Sopenharmony_ci } 485e5c12b0Sopenharmony_ci return nblocks; 495e5c12b0Sopenharmony_ci} 505e5c12b0Sopenharmony_ci 515e5c12b0Sopenharmony_cistatic inline __le32 *blkaddr_in_inode(struct f2fs_node *node) 525e5c12b0Sopenharmony_ci{ 535e5c12b0Sopenharmony_ci return node->i.i_addr + get_extra_isize(node); 545e5c12b0Sopenharmony_ci} 555e5c12b0Sopenharmony_ci 565e5c12b0Sopenharmony_cistatic inline __le32 *blkaddr_in_node(struct f2fs_node *node) 575e5c12b0Sopenharmony_ci{ 585e5c12b0Sopenharmony_ci return IS_INODE(node) ? blkaddr_in_inode(node) : node->dn.addr; 595e5c12b0Sopenharmony_ci} 605e5c12b0Sopenharmony_ci 615e5c12b0Sopenharmony_cistatic inline block_t datablock_addr(struct f2fs_node *node_page, 625e5c12b0Sopenharmony_ci unsigned int offset) 635e5c12b0Sopenharmony_ci{ 645e5c12b0Sopenharmony_ci __le32 *addr_array; 655e5c12b0Sopenharmony_ci 665e5c12b0Sopenharmony_ci ASSERT(node_page); 675e5c12b0Sopenharmony_ci addr_array = blkaddr_in_node(node_page); 685e5c12b0Sopenharmony_ci return le32_to_cpu(addr_array[offset]); 695e5c12b0Sopenharmony_ci} 705e5c12b0Sopenharmony_ci 715e5c12b0Sopenharmony_cistatic inline void set_nid(struct f2fs_node * rn, int off, nid_t nid, int i) 725e5c12b0Sopenharmony_ci{ 735e5c12b0Sopenharmony_ci if (i) 745e5c12b0Sopenharmony_ci rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid); 755e5c12b0Sopenharmony_ci else 765e5c12b0Sopenharmony_ci rn->in.nid[off] = cpu_to_le32(nid); 775e5c12b0Sopenharmony_ci} 785e5c12b0Sopenharmony_ci 795e5c12b0Sopenharmony_cistatic inline nid_t get_nid(struct f2fs_node * rn, int off, int i) 805e5c12b0Sopenharmony_ci{ 815e5c12b0Sopenharmony_ci if (i) 825e5c12b0Sopenharmony_ci return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]); 835e5c12b0Sopenharmony_ci else 845e5c12b0Sopenharmony_ci return le32_to_cpu(rn->in.nid[off]); 855e5c12b0Sopenharmony_ci} 865e5c12b0Sopenharmony_ci 875e5c12b0Sopenharmony_cienum { 885e5c12b0Sopenharmony_ci ALLOC_NODE, /* allocate a new node page if needed */ 895e5c12b0Sopenharmony_ci LOOKUP_NODE, /* lookup up a node without readahead */ 905e5c12b0Sopenharmony_ci LOOKUP_NODE_RA, 915e5c12b0Sopenharmony_ci}; 925e5c12b0Sopenharmony_ci 935e5c12b0Sopenharmony_cistatic inline void set_new_dnode(struct dnode_of_data *dn, 945e5c12b0Sopenharmony_ci struct f2fs_node *iblk, struct f2fs_node *nblk, nid_t nid) 955e5c12b0Sopenharmony_ci{ 965e5c12b0Sopenharmony_ci memset(dn, 0, sizeof(*dn)); 975e5c12b0Sopenharmony_ci dn->inode_blk = iblk; 985e5c12b0Sopenharmony_ci dn->node_blk = nblk; 995e5c12b0Sopenharmony_ci dn->nid = nid; 1005e5c12b0Sopenharmony_ci dn->idirty = 0; 1015e5c12b0Sopenharmony_ci dn->ndirty = 0; 1025e5c12b0Sopenharmony_ci} 1035e5c12b0Sopenharmony_ci 1045e5c12b0Sopenharmony_cistatic inline void inc_inode_blocks(struct dnode_of_data *dn) 1055e5c12b0Sopenharmony_ci{ 1065e5c12b0Sopenharmony_ci u64 blocks = le64_to_cpu(dn->inode_blk->i.i_blocks); 1075e5c12b0Sopenharmony_ci 1085e5c12b0Sopenharmony_ci dn->inode_blk->i.i_blocks = cpu_to_le64(blocks + 1); 1095e5c12b0Sopenharmony_ci dn->idirty = 1; 1105e5c12b0Sopenharmony_ci} 1115e5c12b0Sopenharmony_ci 1125e5c12b0Sopenharmony_cistatic inline int IS_DNODE(struct f2fs_node *node_page) 1135e5c12b0Sopenharmony_ci{ 1145e5c12b0Sopenharmony_ci unsigned int ofs = ofs_of_node(node_page); 1155e5c12b0Sopenharmony_ci 1165e5c12b0Sopenharmony_ci if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK || 1175e5c12b0Sopenharmony_ci ofs == 5 + 2 * NIDS_PER_BLOCK) 1185e5c12b0Sopenharmony_ci return 0; 1195e5c12b0Sopenharmony_ci 1205e5c12b0Sopenharmony_ci if (ofs >= 6 + 2 * NIDS_PER_BLOCK) { 1215e5c12b0Sopenharmony_ci ofs -= 6 + 2 * NIDS_PER_BLOCK; 1225e5c12b0Sopenharmony_ci if (!((long int)ofs % (NIDS_PER_BLOCK + 1))) 1235e5c12b0Sopenharmony_ci return 0; 1245e5c12b0Sopenharmony_ci } 1255e5c12b0Sopenharmony_ci return 1; 1265e5c12b0Sopenharmony_ci} 1275e5c12b0Sopenharmony_ci 1285e5c12b0Sopenharmony_cistatic inline nid_t ino_of_node(struct f2fs_node *node_blk) 1295e5c12b0Sopenharmony_ci{ 1305e5c12b0Sopenharmony_ci return le32_to_cpu(node_blk->footer.ino); 1315e5c12b0Sopenharmony_ci} 1325e5c12b0Sopenharmony_ci 1335e5c12b0Sopenharmony_cistatic inline __u64 cpver_of_node(struct f2fs_node *node_blk) 1345e5c12b0Sopenharmony_ci{ 1355e5c12b0Sopenharmony_ci return le64_to_cpu(node_blk->footer.cp_ver); 1365e5c12b0Sopenharmony_ci} 1375e5c12b0Sopenharmony_ci 1385e5c12b0Sopenharmony_cistatic inline bool is_recoverable_dnode(struct f2fs_sb_info *sbi, 1395e5c12b0Sopenharmony_ci struct f2fs_node *node_blk) 1405e5c12b0Sopenharmony_ci{ 1415e5c12b0Sopenharmony_ci struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); 1425e5c12b0Sopenharmony_ci __u64 cp_ver = cur_cp_version(ckpt); 1435e5c12b0Sopenharmony_ci 1445e5c12b0Sopenharmony_ci /* Don't care crc part, if fsck.f2fs sets it. */ 1455e5c12b0Sopenharmony_ci if (is_set_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG)) 1465e5c12b0Sopenharmony_ci return (cp_ver << 32) == (cpver_of_node(node_blk) << 32); 1475e5c12b0Sopenharmony_ci 1485e5c12b0Sopenharmony_ci if (is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG)) 1495e5c12b0Sopenharmony_ci cp_ver |= (cur_cp_crc(ckpt) << 32); 1505e5c12b0Sopenharmony_ci 1515e5c12b0Sopenharmony_ci return cp_ver == cpver_of_node(node_blk); 1525e5c12b0Sopenharmony_ci} 1535e5c12b0Sopenharmony_ci 1545e5c12b0Sopenharmony_cistatic inline block_t next_blkaddr_of_node(struct f2fs_node *node_blk) 1555e5c12b0Sopenharmony_ci{ 1565e5c12b0Sopenharmony_ci return le32_to_cpu(node_blk->footer.next_blkaddr); 1575e5c12b0Sopenharmony_ci} 1585e5c12b0Sopenharmony_ci 1595e5c12b0Sopenharmony_cistatic inline int is_node(struct f2fs_node *node_blk, int type) 1605e5c12b0Sopenharmony_ci{ 1615e5c12b0Sopenharmony_ci return le32_to_cpu(node_blk->footer.flag) & (1 << type); 1625e5c12b0Sopenharmony_ci} 1635e5c12b0Sopenharmony_ci 1645e5c12b0Sopenharmony_cistatic inline void set_cold_node(struct f2fs_node *rn, bool is_dir) 1655e5c12b0Sopenharmony_ci{ 1665e5c12b0Sopenharmony_ci unsigned int flag = le32_to_cpu(rn->footer.flag); 1675e5c12b0Sopenharmony_ci 1685e5c12b0Sopenharmony_ci if (is_dir) 1695e5c12b0Sopenharmony_ci flag &= ~(0x1 << COLD_BIT_SHIFT); 1705e5c12b0Sopenharmony_ci else 1715e5c12b0Sopenharmony_ci flag |= (0x1 << COLD_BIT_SHIFT); 1725e5c12b0Sopenharmony_ci rn->footer.flag = cpu_to_le32(flag); 1735e5c12b0Sopenharmony_ci} 1745e5c12b0Sopenharmony_ci 1755e5c12b0Sopenharmony_ci#define is_fsync_dnode(node_blk) is_node(node_blk, FSYNC_BIT_SHIFT) 1765e5c12b0Sopenharmony_ci#define is_dent_dnode(node_blk) is_node(node_blk, DENT_BIT_SHIFT) 1775e5c12b0Sopenharmony_ci 1785e5c12b0Sopenharmony_ci#endif 179