/*
* this structure is used as one of function parameters.
* all the information are dedicated to a given direct node block determined
* by the data offset in a file.
*/
struct dnode_of_data {
struct inode *inode; /* vfs inode pointer */
struct page *inode_page; /* its inode page, NULL is possible */ //相关的inode page
struct page *node_page; /* cached direct node page */ //direct node block 的node page
nid_t nid; /* node id of the direct node block */ //direct node block的nid
unsigned int ofs_in_node; /* data offset in the node page */ //node page 中的data offset
bool inode_page_locked; /* inode page is locked or not */
block_t data_blkaddr; /* block address of the node block */ //direct node block 的 block address
};
dnode_of_data 这个结构体用来做为函数的参数,结构体里面的所有成员信息,均来自于与其相关的direct node block,
此direct node block由数据所在的file中的位置决定,即:根据数据所在file中的offset, 找到与其相关的direct node block,
然后填充此direct node block。
/*
* get_node_path - Get the index path of pgoff_t block
* @offset: offset in the current index node block.
* @noffset: NO. of the index block within a file.
* return: depth of the index path.
*
* By default, it sets inline_xattr and inline_data
*
* ==================================
*
* get_node_path: 得到偏移为pgoff_t block对应的路径
* offset: 当前node block中的偏移
* noffset: 一共有多少个索引(index) block(在当前检索到的结点处)
* level: 得到的index path一共有多少层
*
*/
static int get_node_path(struct f2fs_node *node, long block,
int offset[4], unsigned int noffset[4])
{
const long direct_index = ADDRS_PER_INODE(&node->i);
const long direct_blks = ADDRS_PER_BLOCK;
const long dptrs_per_blk = NIDS_PER_BLOCK;
const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
int n = 0;
int level = 0;
/*
* 从inode block开始检索, inode 中共有direct_index个地址,
* 如果block < direct_index,说明此地址存在于inode本身,
* 这时,设置level = 0, offset[0] = block, noffset[0] = 0,
* 说明,inode本身包含此地址,则level = 0,
* block在inode中的偏移为offset[0] = block,
* 索引block, 即index block个数为0, noffset[0] = 0
*/
noffset[0] = 0;
if (block < direct_index) {
offset[n] = block;
goto got;
}
/*
* 如果direct_index < block < direct_blocks, 说明inode 中不包含此地址,
* 但是因其小于direct_blks,则其存在于第一个direct block中。
* 此时,level = 1,index path为1层,
* offset[0] = NODE_DIR1_BLOCKs, 即在inode中的偏移为NODE_DIR1_BLOCKs,
* 通过NODE_DIR1_BLOCKs找到第一层index block的地址,
* offset[1] = block, 其实此block已经为原block - direct_index后剩下的值,
* 即其在第一层index block中的偏移为block.
* noffset[0] = 0, noffset[1] = 1, 说明在此时,index path中的index block为1,
* 即只有一个inode block为index block
*/
block -= direct_index;
if (block < direct_blks) {
offset[n++] = NODE_DIR1_BLOCK;
noffset[n]= 1;
offset[n] = block;
level = 1;
goto got;
}
/*
* 如果 block < direct_blks, 说明inode 中不包含此地址,第一个direct block也不包含此
* 地址,而第二个direct index block中包含此地址。
* 此时,level = 1,index path为1层,
* offset[0] = NODE_DIR2_BLOCK, 为第二个direct index block在inode block中的偏移地址,
* offset[1] = block,为在第二个direct index block中的偏移量,
* noffset[1] = 2, 说明此时,有两个index block,即inode, 和 第一个direct index block。
*/
block -= direct_blks;
if (block < direct_blks) {
offset[n++] = NODE_DIR2_BLOCK;
noffset[n] = 2;
offset[n] = block;
level = 1;
goto got;
}
/*
* 如果block < indirect_blks, 说明inode block中不包含,两个direct index block中也不包含,
* 而是在indirect block中,
* offset[0] = NODE_IND1_BLOCK, 第一个indirect block在inode中的偏移量,
* offset[1] = block / direct_blks, 为其在indirect block中的相当于段地址,
* offset[2] = block % direct_blks, 为其在indirect block中的相当于段内偏移
* noffset[1] = 3, 包含三个index block, inode, direct index block, direct index block,
* noffset[2] = 4, 包含四个index block, inode, 2 * direct index block, indirect block.
* level = 2
* _________________
* | |
* | |
* |_________________| indirect block
* |NODE_IND1_BLOCK |-----> _________
* |_________________| | ... |
* |_________________| |_________|
* |_________________| |offset[1]|----> _________
* |_________| |_________|
* |_________| |offset[2]|---->addr
* |_________| |_________|
* |_________|
*/
block -= direct_blks;
if (block < indirect_blks) {
offset[n++] = NODE_IND1_BLOCK;
noffset[n] = 3;
offset[n++] = block / direct_blks;
noffset[n] = 4 + offset[n - 1];
offset[n] = block % direct_blks;
level = 2;
goto got;
}
block -= indirect_blks;
if (block < indirect_blks) {
offset[n++] = NODE_IND2_BLOCK;
noffset[n] = 4 + dptrs_per_blk;
offset[n++] = block / direct_blks;
noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
offset[n] = block % direct_blks;
level = 2;
goto got;
}
block -= indirect_blks;
if (block < dindirect_blks) {
offset[n++] = NODE_DIND_BLOCK;
noffset[n] = 5 + (dptrs_per_blk * 2);
offset[n++] = block / indirect_blks;
noffset[n] = 6 + (dptrs_per_blk * 2) +
offset[n - 1] * (dptrs_per_blk + 1);
offset[n++] = (block / direct_blks) % dptrs_per_blk;
noffset[n] = 7 + (dptrs_per_blk * 2) +
offset[n - 2] * (dptrs_per_blk + 1) +
offset[n - 1];
offset[n] = block % direct_blks;
level = 3;
goto got;
} else {
ASSERT(0);
}
got:
return level;
}