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