xref: /aosp_15_r20/external/f2fs-tools/fsck/node.h (revision 59bfda1f02d633cd6b8b69f31eee485d40f6eef6)
1*59bfda1fSAndroid Build Coastguard Worker /**
2*59bfda1fSAndroid Build Coastguard Worker  * node.h
3*59bfda1fSAndroid Build Coastguard Worker  *
4*59bfda1fSAndroid Build Coastguard Worker  * Many parts of codes are copied from Linux kernel/fs/f2fs.
5*59bfda1fSAndroid Build Coastguard Worker  *
6*59bfda1fSAndroid Build Coastguard Worker  * Copyright (C) 2015 Huawei Ltd.
7*59bfda1fSAndroid Build Coastguard Worker  * Witten by:
8*59bfda1fSAndroid Build Coastguard Worker  *   Hou Pengyang <[email protected]>
9*59bfda1fSAndroid Build Coastguard Worker  *   Liu Shuoran <[email protected]>
10*59bfda1fSAndroid Build Coastguard Worker  *   Jaegeuk Kim <[email protected]>
11*59bfda1fSAndroid Build Coastguard Worker  *
12*59bfda1fSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify
13*59bfda1fSAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License version 2 as
14*59bfda1fSAndroid Build Coastguard Worker  * published by the Free Software Foundation.
15*59bfda1fSAndroid Build Coastguard Worker  */
16*59bfda1fSAndroid Build Coastguard Worker #ifndef _NODE_H_
17*59bfda1fSAndroid Build Coastguard Worker #define _NODE_H_
18*59bfda1fSAndroid Build Coastguard Worker 
19*59bfda1fSAndroid Build Coastguard Worker #include "fsck.h"
20*59bfda1fSAndroid Build Coastguard Worker 
IS_INODE(struct f2fs_node * node)21*59bfda1fSAndroid Build Coastguard Worker static inline bool IS_INODE(struct f2fs_node *node)
22*59bfda1fSAndroid Build Coastguard Worker {
23*59bfda1fSAndroid Build Coastguard Worker 	return F2FS_NODE_FOOTER(node)->nid == F2FS_NODE_FOOTER(node)->ino;
24*59bfda1fSAndroid Build Coastguard Worker }
25*59bfda1fSAndroid Build Coastguard Worker 
ADDRS_PER_PAGE(struct f2fs_sb_info * sbi,struct f2fs_node * node_blk,struct f2fs_node * inode_blk)26*59bfda1fSAndroid Build Coastguard Worker static inline unsigned int ADDRS_PER_PAGE(struct f2fs_sb_info *sbi,
27*59bfda1fSAndroid Build Coastguard Worker 		struct f2fs_node *node_blk, struct f2fs_node *inode_blk)
28*59bfda1fSAndroid Build Coastguard Worker {
29*59bfda1fSAndroid Build Coastguard Worker 	nid_t ino = le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->ino);
30*59bfda1fSAndroid Build Coastguard Worker 	unsigned int nblocks;
31*59bfda1fSAndroid Build Coastguard Worker 
32*59bfda1fSAndroid Build Coastguard Worker 	if (IS_INODE(node_blk))
33*59bfda1fSAndroid Build Coastguard Worker 		return ADDRS_PER_INODE(&node_blk->i);
34*59bfda1fSAndroid Build Coastguard Worker 
35*59bfda1fSAndroid Build Coastguard Worker 	if (!inode_blk) {
36*59bfda1fSAndroid Build Coastguard Worker 		struct node_info ni;
37*59bfda1fSAndroid Build Coastguard Worker 
38*59bfda1fSAndroid Build Coastguard Worker 		inode_blk = calloc(F2FS_BLKSIZE, 2);
39*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(inode_blk);
40*59bfda1fSAndroid Build Coastguard Worker 
41*59bfda1fSAndroid Build Coastguard Worker 		get_node_info(sbi, ino, &ni);
42*59bfda1fSAndroid Build Coastguard Worker 		ASSERT(dev_read_block(inode_blk, ni.blk_addr) >= 0);
43*59bfda1fSAndroid Build Coastguard Worker 		nblocks = ADDRS_PER_BLOCK(&inode_blk->i);
44*59bfda1fSAndroid Build Coastguard Worker 		free(inode_blk);
45*59bfda1fSAndroid Build Coastguard Worker 	} else {
46*59bfda1fSAndroid Build Coastguard Worker 		nblocks = ADDRS_PER_BLOCK(&inode_blk->i);
47*59bfda1fSAndroid Build Coastguard Worker 	}
48*59bfda1fSAndroid Build Coastguard Worker 	return nblocks;
49*59bfda1fSAndroid Build Coastguard Worker }
50*59bfda1fSAndroid Build Coastguard Worker 
blkaddr_in_inode(struct f2fs_node * node)51*59bfda1fSAndroid Build Coastguard Worker static inline __le32 *blkaddr_in_inode(struct f2fs_node *node)
52*59bfda1fSAndroid Build Coastguard Worker {
53*59bfda1fSAndroid Build Coastguard Worker 	return node->i.i_addr + get_extra_isize(node);
54*59bfda1fSAndroid Build Coastguard Worker }
55*59bfda1fSAndroid Build Coastguard Worker 
blkaddr_in_node(struct f2fs_node * node)56*59bfda1fSAndroid Build Coastguard Worker static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
57*59bfda1fSAndroid Build Coastguard Worker {
58*59bfda1fSAndroid Build Coastguard Worker 	return IS_INODE(node) ? blkaddr_in_inode(node) : node->dn.addr;
59*59bfda1fSAndroid Build Coastguard Worker }
60*59bfda1fSAndroid Build Coastguard Worker 
datablock_addr(struct f2fs_node * node_page,unsigned int offset)61*59bfda1fSAndroid Build Coastguard Worker static inline block_t datablock_addr(struct f2fs_node *node_page,
62*59bfda1fSAndroid Build Coastguard Worker 					unsigned int offset)
63*59bfda1fSAndroid Build Coastguard Worker {
64*59bfda1fSAndroid Build Coastguard Worker 	__le32 *addr_array;
65*59bfda1fSAndroid Build Coastguard Worker 
66*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(node_page);
67*59bfda1fSAndroid Build Coastguard Worker 	addr_array = blkaddr_in_node(node_page);
68*59bfda1fSAndroid Build Coastguard Worker 	return le32_to_cpu(addr_array[offset]);
69*59bfda1fSAndroid Build Coastguard Worker }
70*59bfda1fSAndroid Build Coastguard Worker 
set_nid(struct f2fs_node * rn,int off,nid_t nid,int i)71*59bfda1fSAndroid Build Coastguard Worker static inline void set_nid(struct f2fs_node * rn, int off, nid_t nid, int i)
72*59bfda1fSAndroid Build Coastguard Worker {
73*59bfda1fSAndroid Build Coastguard Worker 	if (i)
74*59bfda1fSAndroid Build Coastguard Worker 		F2FS_INODE_I_NID(&rn->i, off - NODE_DIR1_BLOCK) = cpu_to_le32(nid);
75*59bfda1fSAndroid Build Coastguard Worker 	else
76*59bfda1fSAndroid Build Coastguard Worker 		rn->in.nid[off] = cpu_to_le32(nid);
77*59bfda1fSAndroid Build Coastguard Worker }
78*59bfda1fSAndroid Build Coastguard Worker 
get_nid(struct f2fs_node * rn,int off,int i)79*59bfda1fSAndroid Build Coastguard Worker static inline nid_t get_nid(struct f2fs_node * rn, int off, int i)
80*59bfda1fSAndroid Build Coastguard Worker {
81*59bfda1fSAndroid Build Coastguard Worker 	if (i)
82*59bfda1fSAndroid Build Coastguard Worker 		return le32_to_cpu(F2FS_INODE_I_NID(&rn->i, off - NODE_DIR1_BLOCK));
83*59bfda1fSAndroid Build Coastguard Worker 	else
84*59bfda1fSAndroid Build Coastguard Worker 		return le32_to_cpu(rn->in.nid[off]);
85*59bfda1fSAndroid Build Coastguard Worker }
86*59bfda1fSAndroid Build Coastguard Worker 
87*59bfda1fSAndroid Build Coastguard Worker enum {
88*59bfda1fSAndroid Build Coastguard Worker 	ALLOC_NODE,	/* allocate a new node page if needed */
89*59bfda1fSAndroid Build Coastguard Worker 	LOOKUP_NODE,	/* lookup up a node without readahead */
90*59bfda1fSAndroid Build Coastguard Worker 	LOOKUP_NODE_RA,
91*59bfda1fSAndroid Build Coastguard Worker };
92*59bfda1fSAndroid Build Coastguard Worker 
set_new_dnode(struct dnode_of_data * dn,struct f2fs_node * iblk,struct f2fs_node * nblk,nid_t nid)93*59bfda1fSAndroid Build Coastguard Worker static inline void set_new_dnode(struct dnode_of_data *dn,
94*59bfda1fSAndroid Build Coastguard Worker 		struct f2fs_node *iblk, struct f2fs_node *nblk, nid_t nid)
95*59bfda1fSAndroid Build Coastguard Worker {
96*59bfda1fSAndroid Build Coastguard Worker 	memset(dn, 0, sizeof(*dn));
97*59bfda1fSAndroid Build Coastguard Worker 	dn->inode_blk = iblk;
98*59bfda1fSAndroid Build Coastguard Worker 	dn->node_blk = nblk;
99*59bfda1fSAndroid Build Coastguard Worker 	dn->nid = nid;
100*59bfda1fSAndroid Build Coastguard Worker 	dn->idirty = 0;
101*59bfda1fSAndroid Build Coastguard Worker 	dn->ndirty = 0;
102*59bfda1fSAndroid Build Coastguard Worker 	dn->alloced = 0;
103*59bfda1fSAndroid Build Coastguard Worker }
104*59bfda1fSAndroid Build Coastguard Worker 
inc_inode_blocks(struct dnode_of_data * dn)105*59bfda1fSAndroid Build Coastguard Worker static inline void inc_inode_blocks(struct dnode_of_data *dn)
106*59bfda1fSAndroid Build Coastguard Worker {
107*59bfda1fSAndroid Build Coastguard Worker 	u64 blocks = le64_to_cpu(dn->inode_blk->i.i_blocks);
108*59bfda1fSAndroid Build Coastguard Worker 
109*59bfda1fSAndroid Build Coastguard Worker 	dn->inode_blk->i.i_blocks = cpu_to_le64(blocks + 1);
110*59bfda1fSAndroid Build Coastguard Worker 	dn->idirty = 1;
111*59bfda1fSAndroid Build Coastguard Worker }
112*59bfda1fSAndroid Build Coastguard Worker 
IS_DNODE(struct f2fs_node * node_page)113*59bfda1fSAndroid Build Coastguard Worker static inline int IS_DNODE(struct f2fs_node *node_page)
114*59bfda1fSAndroid Build Coastguard Worker {
115*59bfda1fSAndroid Build Coastguard Worker 	unsigned int ofs = ofs_of_node(node_page);
116*59bfda1fSAndroid Build Coastguard Worker 
117*59bfda1fSAndroid Build Coastguard Worker 	if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK ||
118*59bfda1fSAndroid Build Coastguard Worker 			ofs == 5 + 2 * NIDS_PER_BLOCK)
119*59bfda1fSAndroid Build Coastguard Worker 		return 0;
120*59bfda1fSAndroid Build Coastguard Worker 
121*59bfda1fSAndroid Build Coastguard Worker 	if (ofs >= 6 + 2 * NIDS_PER_BLOCK) {
122*59bfda1fSAndroid Build Coastguard Worker 		ofs -= 6 + 2 * NIDS_PER_BLOCK;
123*59bfda1fSAndroid Build Coastguard Worker 		if (!((long int)ofs % (NIDS_PER_BLOCK + 1)))
124*59bfda1fSAndroid Build Coastguard Worker 			return 0;
125*59bfda1fSAndroid Build Coastguard Worker 	}
126*59bfda1fSAndroid Build Coastguard Worker 	return 1;
127*59bfda1fSAndroid Build Coastguard Worker }
128*59bfda1fSAndroid Build Coastguard Worker 
ino_of_node(struct f2fs_node * node_blk)129*59bfda1fSAndroid Build Coastguard Worker static inline nid_t ino_of_node(struct f2fs_node *node_blk)
130*59bfda1fSAndroid Build Coastguard Worker {
131*59bfda1fSAndroid Build Coastguard Worker 	return le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->ino);
132*59bfda1fSAndroid Build Coastguard Worker }
133*59bfda1fSAndroid Build Coastguard Worker 
cpver_of_node(struct f2fs_node * node_blk)134*59bfda1fSAndroid Build Coastguard Worker static inline __u64 cpver_of_node(struct f2fs_node *node_blk)
135*59bfda1fSAndroid Build Coastguard Worker {
136*59bfda1fSAndroid Build Coastguard Worker 	return le64_to_cpu(F2FS_NODE_FOOTER(node_blk)->cp_ver);
137*59bfda1fSAndroid Build Coastguard Worker }
138*59bfda1fSAndroid Build Coastguard Worker 
is_recoverable_dnode(struct f2fs_sb_info * sbi,struct f2fs_node * node_blk)139*59bfda1fSAndroid Build Coastguard Worker static inline bool is_recoverable_dnode(struct f2fs_sb_info *sbi,
140*59bfda1fSAndroid Build Coastguard Worker 						struct f2fs_node *node_blk)
141*59bfda1fSAndroid Build Coastguard Worker {
142*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
143*59bfda1fSAndroid Build Coastguard Worker 	__u64 cp_ver = cur_cp_version(ckpt);
144*59bfda1fSAndroid Build Coastguard Worker 
145*59bfda1fSAndroid Build Coastguard Worker 	/* Don't care crc part, if fsck.f2fs sets it. */
146*59bfda1fSAndroid Build Coastguard Worker 	if (is_set_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG))
147*59bfda1fSAndroid Build Coastguard Worker 		return (cp_ver << 32) == (cpver_of_node(node_blk) << 32);
148*59bfda1fSAndroid Build Coastguard Worker 
149*59bfda1fSAndroid Build Coastguard Worker 	if (is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG))
150*59bfda1fSAndroid Build Coastguard Worker 		cp_ver |= (cur_cp_crc(ckpt) << 32);
151*59bfda1fSAndroid Build Coastguard Worker 
152*59bfda1fSAndroid Build Coastguard Worker 	return cp_ver == cpver_of_node(node_blk);
153*59bfda1fSAndroid Build Coastguard Worker }
154*59bfda1fSAndroid Build Coastguard Worker 
next_blkaddr_of_node(struct f2fs_node * node_blk)155*59bfda1fSAndroid Build Coastguard Worker static inline block_t next_blkaddr_of_node(struct f2fs_node *node_blk)
156*59bfda1fSAndroid Build Coastguard Worker {
157*59bfda1fSAndroid Build Coastguard Worker 	return le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->next_blkaddr);
158*59bfda1fSAndroid Build Coastguard Worker }
159*59bfda1fSAndroid Build Coastguard Worker 
is_node(struct f2fs_node * node_blk,int type)160*59bfda1fSAndroid Build Coastguard Worker static inline int is_node(struct f2fs_node *node_blk, int type)
161*59bfda1fSAndroid Build Coastguard Worker {
162*59bfda1fSAndroid Build Coastguard Worker 	return le32_to_cpu(F2FS_NODE_FOOTER(node_blk)->flag) & (1 << type);
163*59bfda1fSAndroid Build Coastguard Worker }
164*59bfda1fSAndroid Build Coastguard Worker 
set_cold_node(struct f2fs_node * rn,bool is_dir)165*59bfda1fSAndroid Build Coastguard Worker static inline void set_cold_node(struct f2fs_node *rn, bool is_dir)
166*59bfda1fSAndroid Build Coastguard Worker {
167*59bfda1fSAndroid Build Coastguard Worker 	unsigned int flag = le32_to_cpu(F2FS_NODE_FOOTER(rn)->flag);
168*59bfda1fSAndroid Build Coastguard Worker 
169*59bfda1fSAndroid Build Coastguard Worker 	if (is_dir)
170*59bfda1fSAndroid Build Coastguard Worker 		flag &= ~(0x1 << COLD_BIT_SHIFT);
171*59bfda1fSAndroid Build Coastguard Worker 	else
172*59bfda1fSAndroid Build Coastguard Worker 		flag |= (0x1 << COLD_BIT_SHIFT);
173*59bfda1fSAndroid Build Coastguard Worker 	F2FS_NODE_FOOTER(rn)->flag = cpu_to_le32(flag);
174*59bfda1fSAndroid Build Coastguard Worker }
175*59bfda1fSAndroid Build Coastguard Worker 
176*59bfda1fSAndroid Build Coastguard Worker #define is_fsync_dnode(node_blk)	is_node(node_blk, FSYNC_BIT_SHIFT)
177*59bfda1fSAndroid Build Coastguard Worker #define is_dent_dnode(node_blk)		is_node(node_blk, DENT_BIT_SHIFT)
178*59bfda1fSAndroid Build Coastguard Worker 
179*59bfda1fSAndroid Build Coastguard Worker #endif
180