static void dump_data_offset(u32 blk_addr, int ofs_in_node)
{
	struct f2fs_node *node_blk;
	unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
	unsigned int bidx = 0;
	unsigned int node_ofs;
	int ret;

	node_blk = calloc(BLOCK_SZ, 1);
	ASSERT(node_blk);

	ret = dev_read_block(node_blk, blk_addr);
	ASSERT(ret >= 0);

	node_ofs = ofs_of_node(node_blk);

	if (node_ofs == 0)
		goto got_it;

	if (node_ofs > 0 && node_ofs <= 2) {
		bidx = node_ofs - 1;
	} else if (node_ofs <= indirect_blks) {
		int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
		bidx = node_ofs - 2 - dec;
	} else {
		int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
		bidx = node_ofs - 5 - dec;
	}
	bidx = bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE(&node_blk->i);
got_it:
	bidx +=  ofs_in_node;

	setlocale(LC_ALL, "");
	MSG(0, " - Data offset       : 0x%x (4KB), %'u (bytes)\n",
				bidx, bidx * 4096);
	free(node_blk);
}
static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
					struct f2fs_node *node_blk)
{
	u32 i = 0;
	u64 ofs = 0;

	/* TODO: need to dump xattr */

	if((node_blk->i.i_inline & F2FS_INLINE_DATA)){
		DBG(3, "ino[0x%x] has inline data!\n", nid);
		/* recover from inline data */
		dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET,
							0, MAX_INLINE_DATA);
		return;
	}

	/* check data blocks in inode */
	for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++)
		dump_data_blk(ofs * F2FS_BLKSIZE,
				le32_to_cpu(node_blk->i.i_addr[i]));

	/* check node blocks in inode */
	for (i = 0; i < 5; i++) {
		if (i == 0 || i == 1)
			dump_node_blk(sbi, TYPE_DIRECT_NODE,
					node_blk->i.i_nid[i], &ofs);
		else if (i == 2 || i == 3)
			dump_node_blk(sbi, TYPE_INDIRECT_NODE,
					node_blk->i.i_nid[i], &ofs);
		else if (i == 4)
			dump_node_blk(sbi, TYPE_DOUBLE_INDIRECT_NODE,
					node_blk->i.i_nid[i], &ofs);
		else
			ASSERT(0);
	}
}
Exemple #3
0
int fsck_chk_inode_blk(struct f2fs_sb_info *sbi,
		u32 nid,
		enum FILE_TYPE ftype,
		struct f2fs_node *node_blk,
		u32 *blk_cnt,
		struct node_info *ni)
{
	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
	u32 child_cnt = 0, child_files = 0;
	enum NODE_TYPE ntype;
	u32 i_links = le32_to_cpu(node_blk->i.i_links);
	u64 i_blocks = le64_to_cpu(node_blk->i.i_blocks);
	int idx = 0;
	int ret = 0;

	ASSERT(node_blk->footer.nid == node_blk->footer.ino);
	ASSERT(le32_to_cpu(node_blk->footer.nid) == nid);

	if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap) == 0x0)
		fsck->chk.valid_inode_cnt++;

	/* Orphan node. i_links should be 0 */
	if (ftype == F2FS_FT_ORPHAN) {
		ASSERT(i_links == 0);
	} else {
		ASSERT(i_links > 0);
	}

	if (ftype == F2FS_FT_DIR) {

		/* not included '.' & '..' */
		if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap) != 0) {
			DBG(0, "Duplicated inode blk. ino[0x%x][0x%x]\n", nid, ni->blk_addr);
			ASSERT(0);
		}
		f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap);

	} else {

		if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap) == 0x0) {
			f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap);
			if (i_links > 1) {
				/* First time. Create new hard link node */
				add_into_hard_link_list(sbi, nid, i_links);
				fsck->chk.multi_hard_link_files++;
			}
		} else {
			if (i_links <= 1) {
				DBG(0, "Error. Node ID [0x%x]."
						" There are one more hard links."
						" But i_links is [0x%x]\n",
						nid, i_links);
				ASSERT(0);
			}

			DBG(3, "ino[0x%x] has hard links [0x%x]\n", nid, i_links);
			ret = find_and_dec_hard_link_list(sbi, nid);
			ASSERT(ret >= 0);

			/* No need to go deep into the node */
			goto out;
		}
	}

	fsck_chk_xattr_blk(sbi, nid, le32_to_cpu(node_blk->i.i_xattr_nid), blk_cnt);

	if (ftype == F2FS_FT_CHRDEV || ftype == F2FS_FT_BLKDEV ||
			ftype == F2FS_FT_FIFO || ftype == F2FS_FT_SOCK)
		goto check;
	if((node_blk->i.i_inline & F2FS_INLINE_DATA)){
		DBG(3, "ino[0x%x] has inline data!\n", nid);
		goto check;
	}

	/* check data blocks in inode */
	for (idx = 0; idx < ADDRS_PER_INODE(&node_blk->i); idx++) {
		if (le32_to_cpu(node_blk->i.i_addr[idx]) != 0) {
			*blk_cnt = *blk_cnt + 1;
			ret = fsck_chk_data_blk(sbi,
					&node_blk->i,
					le32_to_cpu(node_blk->i.i_addr[idx]),
					&child_cnt,
					&child_files,
					(i_blocks == *blk_cnt),
					ftype,
					nid,
					idx,
					ni->version);
			ASSERT(ret >= 0);
		}
	}

	/* check node blocks in inode */
	for (idx = 0; idx < 5; idx++) {
		if (idx == 0 || idx == 1)
			ntype = TYPE_DIRECT_NODE;
		else if (idx == 2 || idx == 3)
			ntype = TYPE_INDIRECT_NODE;
		else if (idx == 4)
			ntype = TYPE_DOUBLE_INDIRECT_NODE;
		else
			ASSERT(0);

		if (le32_to_cpu(node_blk->i.i_nid[idx]) != 0) {
			*blk_cnt = *blk_cnt + 1;
			ret = fsck_chk_node_blk(sbi,
					&node_blk->i,
					le32_to_cpu(node_blk->i.i_nid[idx]),
					ftype,
					ntype,
					blk_cnt);
			ASSERT(ret >= 0);
		}
	}
check:
	if (ftype == F2FS_FT_DIR)
		DBG(1, "Directory Inode: ino: %x name: %s depth: %d child files: %d\n\n",
				le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name,
				le32_to_cpu(node_blk->i.i_current_depth), child_files);
	if (ftype == F2FS_FT_ORPHAN)
		DBG(1, "Orphan Inode: ino: %x name: %s i_blocks: %lu\n\n",
				le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name,
				i_blocks);
	if ((ftype == F2FS_FT_DIR && i_links != child_cnt) ||
			(i_blocks != *blk_cnt)) {
		print_node_info(node_blk);
		DBG(1, "blk   cnt [0x%x]\n", *blk_cnt);
		DBG(1, "child cnt [0x%x]\n", child_cnt);
	}

	ASSERT(i_blocks == *blk_cnt);
	if (ftype == F2FS_FT_DIR)
		ASSERT(i_links == child_cnt);
out:
	return 0;
}