f2fs 二三事 get_dnode_of_data

/*
 * Caller should call f2fs_put_dnode(dn).
 * Also, it should grab and release a rwsem by calling f2fs_lock_op() and
 * f2fs_unlock_op() only if ro is not set RDONLY_NODE.
 * In the case of RDONLY_NODE, we don't need to care about mutex.
 */
int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
{
	struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
	struct page *npage[4];
	struct page *parent = NULL;
	int offset[4];
	unsigned int noffset[4];
	nid_t nids[4];
	int level, i;
	int err = 0;

	level = get_node_path(F2FS_I(dn->inode), index, offset, noffset);

	nids[0] = dn->inode->i_ino; //nids[0],代表inode,其nid与i_ino是相等的
	npage[0] = dn->inode_page; //npage[0], inode 对应的inode_page

	if (!npage[0]) {
		npage[0] = get_node_page(sbi, nids[0]);//如果indoe_page为空,则重新获取indoe page
		                                       //从sbi node_inode -> i_mapping里面读取
		if (IS_ERR(npage[0]))
			return PTR_ERR(npage[0]);
	}

	/* if inline_data is set, should not report any block indices */
	if (f2fs_has_inline_data(dn->inode) && index) {
		err = -ENOENT;
		f2fs_put_page(npage[0], 1);
		goto release_out;
	}

	parent = npage[0]; //将parent首先设置为inode
	if (level != 0) 
		nids[1] = get_nid(parent, offset[0], true);//如果level为0,说明inode中包含地址,后面会
		                                           //直接设置dn的信息:
		                                           //dn->inode_page = npage[0]
		                                           //dn->nid = nids[0], 为inode的nid
		                                           //dn->ofs_in_node = offset[0], 为inode中的offset
		                                           //dn->node_page = npage[0], 为inode_page,
		                                           //dn->data_blkaddr,根据inode_page与ofs_in_node,计算data block地址
		                                        
	dn->inode_page = npage[0];
	dn->inode_page_locked = true;

    /* get indirect or direct nodes */
    /* 
    * 如果 level != 0, 则根据返回的level, noffset, offset信息
    * 计算nid, node_page,最后在dn里面填充相应的信息
    */
	for (i = 1; i <= level; i++) {
		bool done = false;

		if (!nids[i] && mode == ALLOC_NODE) {
			/* alloc new node,如果不存在,则申请一个新的nid */
			if (!alloc_nid(sbi, &(nids[i]))) {
				err = -ENOSPC;
				goto release_pages;
			}

			dn->nid = nids[i];
            /* 
             * 如果nid为新申请的nid,得到此nid对应的node_page
             */
			npage[i] = new_node_page(dn, noffset[i], NULL);
			if (IS_ERR(npage[i])) {
				alloc_nid_failed(sbi, nids[i]);
				err = PTR_ERR(npage[i]);
				goto release_pages;
			}
            /*
            * 若i == 1, nids[1] = 为新申请的nid, 则将此nid与inode联系起来,
            * 即,inode_page -> i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
            * 若 i != 1, 则,说明此时i > 1, 此nid已为indirect node,
            * 则设置rn->in.nid[off] = cpu_to_le32(nid);
            */
			set_nid(parent, offset[i - 1], nids[i], i == 1);
			alloc_nid_done(sbi, nids[i]);
			done = true;
		} else if (mode == LOOKUP_NODE_RA && i == level && level > 1) {
			npage[i] = get_node_page_ra(parent, offset[i - 1]);
			if (IS_ERR(npage[i])) {
				err = PTR_ERR(npage[i]);
				goto release_pages;
			}
			done = true;
		}
		if (i == 1) {
			dn->inode_page_locked = false;
			unlock_page(parent);
		} else {
			f2fs_put_page(parent, 1);
		}

		if (!done) {
			npage[i] = get_node_page(sbi, nids[i]);
			if (IS_ERR(npage[i])) {
				err = PTR_ERR(npage[i]);
				f2fs_put_page(npage[0], 0);
				goto release_out;
			}
		}
		if (i < level) {
			parent = npage[i];
			nids[i + 1] = get_nid(parent, offset[i], false);
		}
	}
    /*
     * 最终赋值相应的信息给dn,
     * 即,node_page 对应的nid
     *     ofs_in_node, node_page中的偏移量
     *     node_page, node_page
     *     data_blkaddr: 根据node_page中的偏移,得到最终的block addr
     */
	dn->nid = nids[level];
	dn->ofs_in_node = offset[level];
	dn->node_page = npage[level];
	dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node);
	return 0;

release_pages:
	f2fs_put_page(parent, 1);
	if (i > 1)
		f2fs_put_page(npage[0], 0);
release_out:
	dn->inode_page = NULL;
	dn->node_page = NULL;
	return err;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值