Beispiel #1
0
/* Caller must guarantee that the left bock is good, and written. */
static int search_wrap(struct device *dev,
	uint64_t left_pos, uint64_t *pright_pos,
	const char *stamp_blk, char *probe_blk)
{
	uint64_t high_bit = initial_high_bit_block(dev);
	uint64_t pos = high_bit + left_pos;

	/* The left block must be in the first memory chunk. */
	assert(left_pos < high_bit);

	/* Check that the drive has at least one memory chunk. */
	assert((high_bit - 1) <= *pright_pos);

	while (pos < *pright_pos) {
		if (dev_read_block(dev, probe_blk, pos) &&
			dev_read_block(dev, probe_blk, pos))
			return true;
		/* XXX Deal with flipped bit on reception. */
		if (equal_blk(dev, stamp_blk, probe_blk)) {
			/* XXX Test wraparound hypothesis. */
			*pright_pos = high_bit - 1;
			return false;
		}
		high_bit <<= 1;
		pos = high_bit + left_pos;
	}

	return false;
}
Beispiel #2
0
/* Return true if the test block at @pos is damaged. */
static int test_test_block(struct device *dev,
	const char *stamp_blk, char *probe_blk, uint64_t pos)
{
	if (dev_read_block(dev, probe_blk, pos) &&
		dev_read_block(dev, probe_blk, pos))
		return true;

	return !equal_blk(dev, stamp_blk, probe_blk);
}
int dump_node(struct f2fs_sb_info *sbi, nid_t nid)
{
	struct node_info ni;
	struct f2fs_node *node_blk;
	int ret;

	ret = get_node_info(sbi, nid, &ni);
	ASSERT(ret >= 0);

	node_blk = calloc(BLOCK_SZ, 1);
	dev_read_block(node_blk, ni.blk_addr);

	DBG(1, "Node ID               [0x%x]\n", nid);
	DBG(1, "nat_entry.block_addr  [0x%x]\n", ni.blk_addr);
	DBG(1, "nat_entry.version     [0x%x]\n", ni.version);
	DBG(1, "nat_entry.ino         [0x%x]\n", ni.ino);

	if (ni.blk_addr == 0x0) {
		MSG(0, "Invalid nat entry\n\n");
	}

	DBG(1, "node_blk.footer.ino [0x%x]\n", le32_to_cpu(node_blk->footer.ino));
	DBG(1, "node_blk.footer.nid [0x%x]\n", le32_to_cpu(node_blk->footer.nid));

	if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
			le32_to_cpu(node_blk->footer.nid) == ni.nid) {
		print_node_info(node_blk);
	} else {
		MSG(0, "Invalid node block\n\n");
	}

	free(node_blk);
	return 0;
}
static int find_in_level(struct f2fs_sb_info *sbi,struct f2fs_node *dir,
		unsigned int level, struct dentry *de)
{
	unsigned int nbucket, nblock;
	unsigned int bidx, end_block;
	struct f2fs_dir_entry *dentry = NULL;
	struct dnode_of_data dn;
	void *dentry_blk;
	int max_slots = 214;
	nid_t ino = le32_to_cpu(dir->footer.ino);
	f2fs_hash_t namehash;
	unsigned int dir_level = dir->i.i_dir_level;
	int ret = 0;

	namehash = f2fs_dentry_hash(de->name, de->len);

	nbucket = dir_buckets(level, dir_level);
	nblock = bucket_blocks(level);

	bidx = dir_block_index(level, dir_level, le32_to_cpu(namehash) % nbucket);
	end_block = bidx + nblock;

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

	memset(&dn, 0, sizeof(dn));
	for (; bidx < end_block; bidx++) {

		/* Firstly, we should know direct node of target data blk */
		if (dn.node_blk && dn.node_blk != dn.inode_blk)
			free(dn.node_blk);

		set_new_dnode(&dn, dir, NULL, ino);
		get_dnode_of_data(sbi, &dn, bidx, LOOKUP_NODE);
		if (dn.data_blkaddr == NULL_ADDR)
			continue;

		ret = dev_read_block(dentry_blk, dn.data_blkaddr);
		ASSERT(ret >= 0);

		dentry = find_in_block(dentry_blk, de->name, de->len,
						namehash, &max_slots);
		if (dentry) {
			ret = 1;
			de->ino = le32_to_cpu(dentry->ino);
			break;
		}
	}

	if (dn.node_blk && dn.node_blk != dn.inode_blk)
		free(dn.node_blk);
	free(dentry_blk);

	return ret;
}
static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype,
						u32 nid, u64 *ofs)
{
	struct node_info ni;
	struct f2fs_node *node_blk;
	u32 skip = 0;
	u32 i, idx;

	switch (ntype) {
	case TYPE_DIRECT_NODE:
		skip = idx = ADDRS_PER_BLOCK;
		break;
	case TYPE_INDIRECT_NODE:
		idx = NIDS_PER_BLOCK;
		skip = idx * ADDRS_PER_BLOCK;
		break;
	case TYPE_DOUBLE_INDIRECT_NODE:
		skip = 0;
		idx = NIDS_PER_BLOCK;
		break;
	}

	if (nid == 0) {
		*ofs += skip;
		return;
	}

	get_node_info(sbi, nid, &ni);

	node_blk = calloc(BLOCK_SZ, 1);
	dev_read_block(node_blk, ni.blk_addr);

	for (i = 0; i < idx; i++, (*ofs)++) {
		switch (ntype) {
		case TYPE_DIRECT_NODE:
			dump_data_blk(*ofs * F2FS_BLKSIZE,
					le32_to_cpu(node_blk->dn.addr[i]));
			break;
		case TYPE_INDIRECT_NODE:
			dump_node_blk(sbi, TYPE_DIRECT_NODE,
					le32_to_cpu(node_blk->in.nid[i]), ofs);
			break;
		case TYPE_DOUBLE_INDIRECT_NODE:
			dump_node_blk(sbi, TYPE_INDIRECT_NODE,
					le32_to_cpu(node_blk->in.nid[i]), ofs);
			break;
		}
	}
	free(node_blk);
}
static void dump_node_offset(u32 blk_addr)
{
	struct f2fs_node *node_blk;
	int ret;

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

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

	MSG(0, " - Node offset       : 0x%x\n", ofs_of_node(node_blk));
	free(node_blk);
}
Beispiel #7
0
/* Return true if the block at @pos is damaged. */
static int test_block(struct device *dev,
	const char *stamp_blk, char *probe_blk, uint64_t pos)
{
	/* Write block. */
	if (dev_write_block(dev, stamp_blk, pos) &&
		dev_write_block(dev, stamp_blk, pos))
		return true;

	/* Reset. */
	if (dev_reset(dev) && dev_reset(dev))
		return true;

	/*
	 *	Test block.
	 */

	if (dev_read_block(dev, probe_blk, pos) &&
		dev_read_block(dev, probe_blk, pos))
		return true;

	if (equal_blk(dev, stamp_blk, probe_blk))
		return false;

	/* Save time with certainly damaged blocks. */
	if (!similar_blk(dev, stamp_blk, probe_blk, 8)) {
		/* The probe block is damaged. */
		return true;
	}

	/* The probe block seems to be damaged.
	 * Trying a second time...
	 */
	return 	dev_write_and_reset(dev, stamp_blk, pos) ||
		dev_read_block(dev, probe_blk, pos)  ||
		!equal_blk(dev, stamp_blk, probe_blk);
}
static void dump_node_from_blkaddr(u32 blk_addr)
{
	struct f2fs_node *node_blk;
	int ret;

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

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

	if (config.dbg_lv > 0)
		print_node_info(node_blk);
	else
		print_inode_info(&node_blk->i, 1);

	free(node_blk);
}
Beispiel #9
0
/*
 read
 Read characters from a file. `libc' subroutines will use this system routine for input from all files, including stdin
 Returns -1 on error or blocks until the number of characters have been read.
 */
int _read(int file, char *ptr, int len) 
{
  int dev_num;

  if (len == 0)
    return 0;
       
  if (file < MAX_FILES)
  {
    dev_num = file_table [file].dev_major;
    dev_read_block (&DriverTable[dev_num], file_table [file].dev_minor, ptr, len);
    return len;
  }
  else
  {
    errno = EBADF;
    return -1;
  }
}
static void dump_data_blk(__u64 offset, u32 blkaddr)
{
	char buf[F2FS_BLKSIZE];

	if (blkaddr == NULL_ADDR)
		return;

	/* get data */
	if (blkaddr == NEW_ADDR) {
		memset(buf, 0, F2FS_BLKSIZE);
	} else {
		int ret;
		ret = dev_read_block(buf, blkaddr);
		ASSERT(ret >= 0);
	}

	/* write blkaddr */
	dev_write_dump(buf, offset, F2FS_BLKSIZE);
}
int dump_inode_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
{
	nid_t ino, nid;
	int type, ret;
	struct f2fs_summary sum_entry;
	struct node_info ni;
	struct f2fs_node *node_blk;

	type = get_sum_entry(sbi, blk_addr, &sum_entry);
	nid = le32_to_cpu(sum_entry.nid);

	ret = get_node_info(sbi, nid, &ni);
	ASSERT(ret >= 0);

	DBG(1, "Note: blkaddr = main_blkaddr + segno * 512 + offset\n");
	DBG(1, "Block_addr            [0x%x]\n", blk_addr);
	DBG(1, " - Segno              [0x%x]\n", GET_SEGNO(sbi, blk_addr));
	DBG(1, " - Offset             [0x%x]\n", OFFSET_IN_SEG(sbi, blk_addr));
	DBG(1, "SUM.nid               [0x%x]\n", nid);
	DBG(1, "SUM.type              [%s]\n", seg_type_name[type]);
	DBG(1, "SUM.version           [%d]\n", sum_entry.version);
	DBG(1, "SUM.ofs_in_node       [%d]\n", sum_entry.ofs_in_node);
	DBG(1, "NAT.blkaddr           [0x%x]\n", ni.blk_addr);
	DBG(1, "NAT.ino               [0x%x]\n", ni.ino);

	node_blk = calloc(BLOCK_SZ, 1);

read_node_blk:
	dev_read_block(node_blk, blk_addr);

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

	if (ino == nid) {
		print_node_info(node_blk);
	} else {
		ret = get_node_info(sbi, ino, &ni);
		goto read_node_blk;
	}

	free(node_blk);
	return ino;
}
int f2fs_find_path(struct f2fs_sb_info *sbi, char *path, nid_t *ino)
{
	struct f2fs_node *parent;
	struct node_info ni;
	struct dentry de;
	int err = 0;
	int ret;
	char *p;

	if (path[0] != '/')
		return -ENOENT;

	*ino = F2FS_ROOT_INO(sbi);
	parent = calloc(BLOCK_SZ, 1);
	ASSERT(parent);

	p = strtok(path, "/");
	while (p) {
		de.name = (const u8 *)p;
		de.len = strlen(p);

		get_node_info(sbi, *ino, &ni);
		if (ni.blk_addr == NULL_ADDR) {
			err = -ENOENT;
			goto err;
		}
		ret = dev_read_block(parent, ni.blk_addr);
		ASSERT(ret >= 0);

		ret = f2fs_find_entry(sbi, parent, &de);
		if (!ret) {
			err = -ENOENT;
			goto err;
		}

		*ino = de.ino;
		p = strtok(NULL, "/");
	}
err:
	free(parent);
	return err;
}
Beispiel #13
0
int fsck_chk_orphan_node(struct f2fs_sb_info *sbi)
{
	int ret = 0;
	u32 blk_cnt = 0;

	block_t start_blk, orphan_blkaddr, i, j;
	struct f2fs_orphan_block *orphan_blk;

	if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG))
		return 0;

	start_blk = __start_cp_addr(sbi) + 1;
	orphan_blkaddr = __start_sum_addr(sbi) - 1;

	orphan_blk = calloc(BLOCK_SZ, 1);

	for (i = 0; i < orphan_blkaddr; i++) {
		dev_read_block(orphan_blk, start_blk + i);

		for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) {
			nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
			DBG(1, "[%3d] ino [0x%x]\n", i, ino);
			blk_cnt = 1;
			ret = fsck_chk_node_blk(sbi,
					NULL,
					ino,
					F2FS_FT_ORPHAN,
					TYPE_INODE,
					&blk_cnt);
			ASSERT(ret >= 0);
		}
		memset(orphan_blk, 0, BLOCK_SZ);
	}
	free(orphan_blk);


	return 0;
}
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);
}
void get_dnode_of_data(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
						pgoff_t index, int mode)
{
	int offset[4];
	unsigned int noffset[4];
	struct f2fs_node *parent = NULL;
	nid_t nids[4];
	block_t nblk[4];
	struct node_info ni;
	int level, i;
	int ret;

	level = get_node_path(index, offset, noffset);

	nids[0] = dn->nid;
	parent = dn->inode_blk;
	if (level != 0)
		nids[1] = get_nid(parent, offset[0], 1);
	else
		dn->node_blk = dn->inode_blk;

	get_node_info(sbi, nids[0], &ni);
	nblk[0] = ni.blk_addr;

	for (i = 1; i <= level; i++) {
		if (!nids[i] && mode == ALLOC_NODE) {
			f2fs_alloc_nid(sbi, &nids[i], 0);

			dn->nid = nids[i];

			/* Function new_node_blk get a new f2fs_node blk and update*/
			/* We should make sure that dn->node_blk == NULL*/
			nblk[i] = new_node_block(sbi, dn, noffset[i]);
			ASSERT(nblk[i]);

			set_nid(parent, offset[i - 1], nids[i], i == 1);
		} else {
			/* If Sparse file no read API, */
			struct node_info ni;

			get_node_info(sbi, nids[i], &ni);
			dn->node_blk = calloc(BLOCK_SZ, 1);
			ASSERT(dn->node_blk);

			ret = dev_read_block(dn->node_blk, ni.blk_addr);
			ASSERT(ret >= 0);

			nblk[i] = ni.blk_addr;
		}

		if (mode == ALLOC_NODE){
			/* Parent node may have changed */
			ret = dev_write_block(parent, nblk[i - 1]);
			ASSERT(ret >= 0);
		}
		if (i != 1)
			free(parent);

		if (i < level) {
			parent = dn->node_blk;
			nids[i + 1] = get_nid(parent, offset[i], 0);
		}
	}

	dn->nid = nids[level];
	dn->ofs_in_node = offset[level];
	dn->data_blkaddr = datablock_addr(dn->node_blk, dn->ofs_in_node);
	dn->node_blkaddr = nblk[level];
}
int f2fs_create(struct f2fs_sb_info *sbi, struct dentry *de)
{
	struct f2fs_node *parent, *child;
	struct node_info ni;
	struct f2fs_summary sum;
	block_t blkaddr = NULL_ADDR;
	int ret;

	/* Find if there is a */
	get_node_info(sbi, de->pino, &ni);
	if (ni.blk_addr == NULL_ADDR) {
		MSG(0, "No parent directory pino=%x\n", de->pino);
		return -1;
	}

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

	ret = dev_read_block(parent, ni.blk_addr);
	ASSERT(ret >= 0);

	/* Must convert inline dentry before the following opertions */
	ret = convert_inline_dentry(sbi, parent, ni.blk_addr);
	if (ret) {
		MSG(0, "Convert inline dentry for pino=%x failed.\n", de->pino);
		return -1;
	}

	ret = f2fs_find_entry(sbi, parent, de);
	if (ret) {
		MSG(0, "Skip the existing \"%s\" pino=%x ERR=%d\n",
					de->name, de->pino, ret);
		if (de->file_type == F2FS_FT_REG_FILE)
			de->ino = 0;
		goto free_parent_dir;
	}

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

	f2fs_alloc_nid(sbi, &de->ino, 1);

	init_inode_block(sbi, child, de);

	ret = f2fs_add_link(sbi, parent, child->i.i_name,
				le32_to_cpu(child->i.i_namelen),
				le32_to_cpu(child->footer.ino),
				map_de_type(le16_to_cpu(child->i.i_mode)),
				ni.blk_addr, 1);
	if (ret) {
		MSG(0, "Skip the existing \"%s\" pino=%x ERR=%d\n",
					de->name, de->pino, ret);
		goto free_child_dir;
	}

	/* write child */
	set_summary(&sum, de->ino, 0, ni.version);
	reserve_new_block(sbi, &blkaddr, &sum, CURSEG_HOT_NODE);

	/* update nat info */
	update_nat_blkaddr(sbi, de->ino, de->ino, blkaddr);

	ret = dev_write_block(child, blkaddr);
	ASSERT(ret >= 0);

	update_free_segments(sbi);
	MSG(1, "Info: Create %s -> %s\n"
		"  -- ino=%x, type=%x, mode=%x, uid=%x, "
		"gid=%x, cap=%"PRIx64", size=%lu, pino=%x\n",
		de->full_path, de->path,
		de->ino, de->file_type, de->mode,
		de->uid, de->gid, de->capabilities, de->size, de->pino);
free_child_dir:
	free(child);
free_parent_dir:
	free(parent);
	return 0;
}
/*
 * f2fs_add_link - Add a new file(dir) to parent dir.
 */
int f2fs_add_link(struct f2fs_sb_info *sbi, struct f2fs_node *parent,
			const unsigned char *name, int name_len, nid_t ino,
			int file_type, block_t p_blkaddr, int inc_link)
{
	int level = 0, current_depth, bit_pos;
	int nbucket, nblock, bidx, block;
	int slots = GET_DENTRY_SLOTS(name_len);
	f2fs_hash_t dentry_hash = f2fs_dentry_hash(name, name_len);
	struct f2fs_dentry_block *dentry_blk;
	struct f2fs_dentry_ptr d;
	struct dnode_of_data dn;
	nid_t pino = le32_to_cpu(parent->footer.ino);
	unsigned int dir_level = parent->i.i_dir_level;
	int ret;

	if (parent == NULL)
		return -EINVAL;

	if (!pino) {
		ERR_MSG("Wrong parent ino:%d \n", pino);
		return -EINVAL;
	}

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

	current_depth = le32_to_cpu(parent->i.i_current_depth);
start:
	if (current_depth == MAX_DIR_HASH_DEPTH) {
		free(dentry_blk);
		ERR_MSG("\tError: MAX_DIR_HASH\n");
		return -ENOSPC;
	}

	/* Need a new dentry block */
	if (level == current_depth)
		++current_depth;

	nbucket = dir_buckets(level, dir_level);
	nblock = bucket_blocks(level);
	bidx = dir_block_index(level, dir_level, le32_to_cpu(dentry_hash) % nbucket);

	memset(&dn, 0, sizeof(dn));
	for (block = bidx; block <= (bidx + nblock - 1); block++) {

		/* Firstly, we should know the direct node of target data blk */
		if (dn.node_blk && dn.node_blk != dn.inode_blk)
			free(dn.node_blk);

		set_new_dnode(&dn, parent, NULL, pino);
		get_dnode_of_data(sbi, &dn, block, ALLOC_NODE);

		if (dn.data_blkaddr == NULL_ADDR) {
			new_data_block(sbi, dentry_blk, &dn, CURSEG_HOT_DATA);
		} else {
			ret = dev_read_block(dentry_blk, dn.data_blkaddr);
			ASSERT(ret >= 0);
		}
		bit_pos = room_for_filename(dentry_blk->dentry_bitmap,
				slots, NR_DENTRY_IN_BLOCK);

		if (bit_pos < NR_DENTRY_IN_BLOCK)
			goto add_dentry;
	}
	level ++;
	goto start;

add_dentry:
	make_dentry_ptr(&d, NULL, (void *)dentry_blk, 1);
	f2fs_update_dentry(ino, file_type, &d, name, name_len, dentry_hash, bit_pos);

	ret = dev_write_block(dentry_blk, dn.data_blkaddr);
	ASSERT(ret >= 0);

	/*
	 * Parent inode needs updating, because its inode info may be changed.
	 * such as i_current_depth and i_blocks.
	 */
	if (parent->i.i_current_depth != cpu_to_le32(current_depth)) {
		parent->i.i_current_depth = cpu_to_le32(current_depth);
		dn.idirty = 1;
	}

	/* Update parent's i_links info*/
	if (inc_link && (file_type == F2FS_FT_DIR)){
		u32 links = le32_to_cpu(parent->i.i_links);
		parent->i.i_links = cpu_to_le32(links + 1);
		dn.idirty = 1;
	}

	if ((__u64)((block + 1) * F2FS_BLKSIZE) >
					le64_to_cpu(parent->i.i_size)) {
		parent->i.i_size = cpu_to_le64((block + 1) * F2FS_BLKSIZE);
		dn.idirty = 1;
	}

	if (dn.ndirty) {
		ret = dev_write_block(dn.node_blk, dn.node_blkaddr);
		ASSERT(ret >= 0);
	}

	if (dn.idirty) {
		ASSERT(parent == dn.inode_blk);
		ret = dev_write_block(dn.inode_blk, p_blkaddr);
		ASSERT(ret >= 0);
	}

	if (dn.node_blk != dn.inode_blk)
		free(dn.node_blk);
	free(dentry_blk);
	return 0;
}
Beispiel #18
0
int fsck_chk_node_blk(struct f2fs_sb_info *sbi,
		struct f2fs_inode *inode,
		u32 nid,
		enum FILE_TYPE ftype,
		enum NODE_TYPE ntype,
		u32 *blk_cnt)
{
	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
	struct node_info ni;
	struct f2fs_node *node_blk = NULL;
	int ret = 0;

	IS_VALID_NID(sbi, nid);

	if (ftype != F2FS_FT_ORPHAN ||
			f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0x0)
		f2fs_clear_bit(nid, fsck->nat_area_bitmap);
	else
		ASSERT_MSG(0, "nid duplicated [0x%x]\n", nid);

	ret = get_node_info(sbi, nid, &ni);
	ASSERT(ret >= 0);

	/* Is it reserved block?
	 * if block addresss was 0xffff,ffff,ffff,ffff
	 * it means that block was already allocated, but not stored in disk
	 */
	if (ni.blk_addr == NEW_ADDR) {
		fsck->chk.valid_blk_cnt++;
		fsck->chk.valid_node_cnt++;
		if (ntype == TYPE_INODE)
			fsck->chk.valid_inode_cnt++;
		return 0;
	}

	IS_VALID_BLK_ADDR(sbi, ni.blk_addr);

	is_valid_ssa_node_blk(sbi, nid, ni.blk_addr);

	if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->sit_area_bitmap) == 0x0) {
		DBG(0, "SIT bitmap is 0x0. blk_addr[0x%x] %i\n", ni.blk_addr, ni.blk_addr);
		ASSERT(0);
	}else{
		DBG(0, "SIT bitmap is NOT 0x0. blk_addr[0x%x] %i\n", ni.blk_addr, ni.blk_addr);
		//ASSERT(0);
	}

	if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->main_area_bitmap) == 0x0) {
		DBG(0, "SIT and main bitmap is 0x0. blk_addr[0x%x] %i\n", ni.blk_addr, ni.blk_addr);
		fsck->chk.valid_blk_cnt++;
		fsck->chk.valid_node_cnt++;
	}else{
		DBG(0, "SIT and main bitmap is NOT 0x0. blk_addr[0x%x] %i\n", ni.blk_addr, ni.blk_addr);
	    
	}

	node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
	ASSERT(node_blk != NULL);

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

	ASSERT_MSG(nid == le32_to_cpu(node_blk->footer.nid),
			"nid[0x%x] blk_addr[0x%x] footer.nid[0x%x]\n",
			nid, ni.blk_addr, le32_to_cpu(node_blk->footer.nid));

	if (ntype == TYPE_INODE) {
		ret = fsck_chk_inode_blk(sbi,
				nid,
				ftype,
				node_blk,
				blk_cnt,
				&ni);
	} else {
		/* it's not inode */
		ASSERT(node_blk->footer.nid != node_blk->footer.ino);

		if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->main_area_bitmap) != 0) {
			DBG(0, "Duplicated node block. 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);

		switch (ntype) {
		case TYPE_DIRECT_NODE:
			ret = fsck_chk_dnode_blk(sbi,
					inode,
					nid,
					ftype,
					node_blk,
					blk_cnt,
					&ni);
			break;
		case TYPE_INDIRECT_NODE:
			ret = fsck_chk_idnode_blk(sbi,
					inode,
					nid,
					ftype,
					node_blk,
					blk_cnt);
			break;
		case TYPE_DOUBLE_INDIRECT_NODE:
			ret = fsck_chk_didnode_blk(sbi,
					inode,
					nid,
					ftype,
					node_blk,
					blk_cnt);
			break;
		default:
			ASSERT(0);
		}
	}
	ASSERT(ret >= 0);

	free(node_blk);
	return 0;
}
Beispiel #19
0
int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi,
		struct f2fs_inode *inode,
		u32 blk_addr,
		u32 *child_cnt,
		u32 *child_files,
		int last_blk)
{
	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
	int i;
	int ret = 0;
	int dentries = 0;
	u8 *name;
	u32 hash_code;
	u32 blk_cnt;
	u16 name_len;;

	enum FILE_TYPE ftype;
	struct f2fs_dentry_block *de_blk;

	de_blk = (struct f2fs_dentry_block *)calloc(BLOCK_SZ, 1);
	ASSERT(de_blk != NULL);

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

	fsck->dentry_depth++;

	for (i = 0; i < NR_DENTRY_IN_BLOCK;) {
		if (test_bit(i, (unsigned long *)de_blk->dentry_bitmap) == 0x0) {
			i++;
			continue;
		}

		name_len = le32_to_cpu(de_blk->dentry[i].name_len);
		name = calloc(name_len + 1, 1);
		memcpy(name, de_blk->filename[i], name_len);

		hash_code = f2fs_dentry_hash((const char *)name, name_len);
		ASSERT(le32_to_cpu(de_blk->dentry[i].hash_code) == hash_code);

		ftype = de_blk->dentry[i].file_type;

		/* Becareful. 'dentry.file_type' is not imode. */
		if (ftype == F2FS_FT_DIR) {
			*child_cnt = *child_cnt + 1;
			if ((name[0] == '.' && name[1] == '.' && name_len == 2) ||
					(name[0] == '.' && name_len == 1)) {
				i++;
				free(name);
				continue;
			}
		}

		DBG(2, "[%3u] - no[0x%x] name[%s] len[0x%x] ino[0x%x] type[0x%x]\n",
				fsck->dentry_depth, i, name, name_len,
				le32_to_cpu(de_blk->dentry[i].ino),
				de_blk->dentry[i].file_type);

		print_dentry(fsck->dentry_depth, name, de_blk, i, last_blk);

		blk_cnt = 1;
		ret = fsck_chk_node_blk(sbi,
				NULL,
				le32_to_cpu(de_blk->dentry[i].ino),
				ftype,
				TYPE_INODE,
				&blk_cnt);

		ASSERT(ret >= 0);

		i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN;
		dentries++;
		*child_files = *child_files + 1;
		free(name);
	}

	DBG(1, "[%3d] Dentry Block [0x%x] Done : dentries:%d in %d slots (len:%d)\n\n",
			fsck->dentry_depth, blk_addr, dentries, NR_DENTRY_IN_BLOCK, F2FS_NAME_LEN);
	fsck->dentry_depth--;

	free(de_blk);
	return 0;
}