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 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; }
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; }