1 /**
2  * node.h
3  *
4  * Many parts of codes are copied from Linux kernel/fs/f2fs.
5  *
6  * Copyright (C) 2015 Huawei Ltd.
7  * Witten by:
8  *   Hou Pengyang <houpengyang@huawei.com>
9  *   Liu Shuoran <liushuoran@huawei.com>
10  *   Jaegeuk Kim <jaegeuk@kernel.org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2 as
14  * published by the Free Software Foundation.
15  */
16 #ifndef _NODE_H_
17 #define _NODE_H_
18 
19 #include "fsck.h"
20 
21 #define ADDRS_PER_PAGE(page) \
22 	(IS_INODE(page) ? ADDRS_PER_INODE(&page->i) : ADDRS_PER_BLOCK)
23 
IS_INODE(struct f2fs_node * node)24 static inline int IS_INODE(struct f2fs_node *node)
25 {
26 	return ((node)->footer.nid == (node)->footer.ino);
27 }
28 
blkaddr_in_inode(struct f2fs_node * node)29 static inline __le32 *blkaddr_in_inode(struct f2fs_node *node)
30 {
31 	return node->i.i_addr + get_extra_isize(node);
32 }
33 
blkaddr_in_node(struct f2fs_node * node)34 static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
35 {
36 	return IS_INODE(node) ? blkaddr_in_inode(node) : node->dn.addr;
37 }
38 
datablock_addr(struct f2fs_node * node_page,unsigned int offset)39 static inline block_t datablock_addr(struct f2fs_node *node_page,
40 					unsigned int offset)
41 {
42 	__le32 *addr_array;
43 
44 	ASSERT(node_page);
45 	addr_array = blkaddr_in_node(node_page);
46 	return le32_to_cpu(addr_array[offset]);
47 }
48 
set_nid(struct f2fs_node * rn,int off,nid_t nid,int i)49 static inline void set_nid(struct f2fs_node * rn, int off, nid_t nid, int i)
50 {
51 	if (i)
52 		rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
53 	else
54 		rn->in.nid[off] = cpu_to_le32(nid);
55 }
56 
get_nid(struct f2fs_node * rn,int off,int i)57 static inline nid_t get_nid(struct f2fs_node * rn, int off, int i)
58 {
59 	if (i)
60 		return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]);
61 	else
62 		return le32_to_cpu(rn->in.nid[off]);
63 }
64 
65 enum {
66 	ALLOC_NODE,	/* allocate a new node page if needed */
67 	LOOKUP_NODE,	/* lookup up a node without readahead */
68 	LOOKUP_NODE_RA,
69 };
70 
set_new_dnode(struct dnode_of_data * dn,struct f2fs_node * iblk,struct f2fs_node * nblk,nid_t nid)71 static inline void set_new_dnode(struct dnode_of_data *dn,
72 		struct f2fs_node *iblk, struct f2fs_node *nblk, nid_t nid)
73 {
74 	memset(dn, 0, sizeof(*dn));
75 	dn->inode_blk = iblk;
76 	dn->node_blk = nblk;
77 	dn->nid = nid;
78 	dn->idirty = 0;
79 	dn->ndirty = 0;
80 }
81 
inc_inode_blocks(struct dnode_of_data * dn)82 static inline void inc_inode_blocks(struct dnode_of_data *dn)
83 {
84 	u64 blocks = le64_to_cpu(dn->inode_blk->i.i_blocks);
85 
86 	dn->inode_blk->i.i_blocks = cpu_to_le64(blocks + 1);
87 	dn->idirty = 1;
88 }
89 
IS_DNODE(struct f2fs_node * node_page)90 static inline int IS_DNODE(struct f2fs_node *node_page)
91 {
92 	unsigned int ofs = ofs_of_node(node_page);
93 
94 	if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK ||
95 			ofs == 5 + 2 * NIDS_PER_BLOCK)
96 		return 0;
97 
98 	if (ofs >= 6 + 2 * NIDS_PER_BLOCK) {
99 		ofs -= 6 + 2 * NIDS_PER_BLOCK;
100 		if (!((long int)ofs % (NIDS_PER_BLOCK + 1)))
101 			return 0;
102 	}
103 	return 1;
104 }
105 
106 #endif
107