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;
}
Beispiel #2
0
static struct f2fs_dir_entry *find_in_level(struct inode *dir,
		unsigned int level, const char *name, size_t namelen,
			f2fs_hash_t namehash, struct page **res_page)
{
	int s = GET_DENTRY_SLOTS(namelen);
	unsigned int nbucket, nblock;
	unsigned int bidx, end_block;
	struct page *dentry_page;
	struct f2fs_dir_entry *de = NULL;
	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
	bool room = false;
	int max_slots = 0;

	f2fs_bug_on(level > MAX_DIR_HASH_DEPTH);

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

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

	for (; bidx < end_block; bidx++) {
		bool nocase = false;

		/* no need to allocate new dentry pages to all the indices */
		dentry_page = find_data_page(dir, bidx, true);
		if (IS_ERR(dentry_page)) {
			room = true;
			continue;
		}

		if (test_opt(sbi, ANDROID_EMU) &&
		    (sbi->android_emu_flags & F2FS_ANDROID_EMU_NOCASE) &&
		    F2FS_I(dir)->i_advise & FADVISE_ANDROID_EMU)
			nocase = true;

		de = find_in_block(dentry_page, name, namelen,
					&max_slots, namehash, res_page,
					nocase);
		if (de)
			break;

		if (max_slots >= s)
			room = true;
		f2fs_put_page(dentry_page, 0);
	}

	if (!de && room && F2FS_I(dir)->chash != namehash) {
		F2FS_I(dir)->chash = namehash;
		F2FS_I(dir)->clevel = level;
	}

	return de;
}
Beispiel #3
0
static struct f2fs_dir_entry *find_in_level(struct inode *dir,
			unsigned int level, struct qstr *name,
			f2fs_hash_t namehash, struct page **res_page,
			unsigned int flags)
{
	int s = GET_DENTRY_SLOTS(name->len);
	unsigned int nbucket, nblock;
	unsigned int bidx, end_block;
	struct page *dentry_page;
	struct f2fs_dir_entry *de = NULL;
	bool room = false;
	int max_slots;

	f2fs_bug_on(F2FS_I_SB(dir), level > MAX_DIR_HASH_DEPTH);

	nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level);
	nblock = bucket_blocks(level);

	bidx = dir_block_index(level, F2FS_I(dir)->i_dir_level,
					le32_to_cpu(namehash) % nbucket);
	end_block = bidx + nblock;

	for (; bidx < end_block; bidx++) {
		/* no need to allocate new dentry pages to all the indices */
		dentry_page = find_data_page(dir, bidx, true);
		if (IS_ERR(dentry_page)) {
			room = true;
			continue;
		}

		de = find_in_block(dentry_page, name, &max_slots,
					res_page, flags);
		if (de)
			break;

		if (max_slots >= s)
			room = true;
		f2fs_put_page(dentry_page, 0);
	}

	if (!de && room && F2FS_I(dir)->chash != namehash) {
		F2FS_I(dir)->chash = namehash;
		F2FS_I(dir)->clevel = level;
	}

	return de;
}