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
24static inline int IS_INODE(struct f2fs_node *node)
25{
26	return ((node)->footer.nid == (node)->footer.ino);
27}
28
29static inline __le32 *blkaddr_in_inode(struct f2fs_node *node)
30{
31	return node->i.i_addr + get_extra_isize(node);
32}
33
34static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
35{
36	return IS_INODE(node) ? blkaddr_in_inode(node) : node->dn.addr;
37}
38
39static 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
49static 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
57static 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
65enum {
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
71static 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
82static 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
90static 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