/** * node.h * * Many parts of codes are copied from Linux kernel/fs/f2fs. * * Copyright (C) 2015 Huawei Ltd. * Witten by: * Hou Pengyang <houpengyang@huawei.com> * Liu Shuoran <liushuoran@huawei.com> * Jaegeuk Kim <jaegeuk@kernel.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #ifndef _NODE_H_ #define _NODE_H_ #include "fsck.h" #define ADDRS_PER_PAGE(page) \ (IS_INODE(page) ? ADDRS_PER_INODE(&page->i) : ADDRS_PER_BLOCK) static inline int IS_INODE(struct f2fs_node *node) { return ((node)->footer.nid == (node)->footer.ino); } static inline __le32 *blkaddr_in_inode(struct f2fs_node *node) { return node->i.i_addr + get_extra_isize(node); } static inline __le32 *blkaddr_in_node(struct f2fs_node *node) { return IS_INODE(node) ? blkaddr_in_inode(node) : node->dn.addr; } static inline block_t datablock_addr(struct f2fs_node *node_page, unsigned int offset) { __le32 *addr_array; ASSERT(node_page); addr_array = blkaddr_in_node(node_page); return le32_to_cpu(addr_array[offset]); } static inline void set_nid(struct f2fs_node * rn, int off, nid_t nid, int i) { if (i) rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid); else rn->in.nid[off] = cpu_to_le32(nid); } static inline nid_t get_nid(struct f2fs_node * rn, int off, int i) { if (i) return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]); else return le32_to_cpu(rn->in.nid[off]); } enum { ALLOC_NODE, /* allocate a new node page if needed */ LOOKUP_NODE, /* lookup up a node without readahead */ LOOKUP_NODE_RA, }; static inline void set_new_dnode(struct dnode_of_data *dn, struct f2fs_node *iblk, struct f2fs_node *nblk, nid_t nid) { memset(dn, 0, sizeof(*dn)); dn->inode_blk = iblk; dn->node_blk = nblk; dn->nid = nid; dn->idirty = 0; dn->ndirty = 0; } static inline void inc_inode_blocks(struct dnode_of_data *dn) { u64 blocks = le64_to_cpu(dn->inode_blk->i.i_blocks); dn->inode_blk->i.i_blocks = cpu_to_le64(blocks + 1); dn->idirty = 1; } static inline int IS_DNODE(struct f2fs_node *node_page) { unsigned int ofs = ofs_of_node(node_page); if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK || ofs == 5 + 2 * NIDS_PER_BLOCK) return 0; if (ofs >= 6 + 2 * NIDS_PER_BLOCK) { ofs -= 6 + 2 * NIDS_PER_BLOCK; if (!((long int)ofs % (NIDS_PER_BLOCK + 1))) return 0; } return 1; } #endif