Loading fs/f2fs/dir.c +46 −27 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ static unsigned long dir_block_index(unsigned int level, return bidx; } bool early_match_name(size_t namelen, f2fs_hash_t namehash, static bool early_match_name(size_t namelen, f2fs_hash_t namehash, struct f2fs_dir_entry *de) { if (le16_to_cpu(de->name_len) != namelen) Loading @@ -91,48 +91,68 @@ bool early_match_name(size_t namelen, f2fs_hash_t namehash, static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, struct qstr *name, int *max_slots, f2fs_hash_t namehash, struct page **res_page) struct page **res_page) { struct f2fs_dentry_block *dentry_blk; struct f2fs_dir_entry *de; *max_slots = NR_DENTRY_IN_BLOCK; dentry_blk = (struct f2fs_dentry_block *)kmap(dentry_page); de = find_target_dentry(name, max_slots, &dentry_blk->dentry_bitmap, dentry_blk->dentry, dentry_blk->filename); if (de) *res_page = dentry_page; else kunmap(dentry_page); /* * For the most part, it should be a bug when name_len is zero. * We stop here for figuring out where the bugs has occurred. */ f2fs_bug_on(F2FS_P_SB(dentry_page), *max_slots < 0); return de; } struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots, const void *bitmap, struct f2fs_dir_entry *dentry, __u8 (*filenames)[F2FS_SLOT_LEN]) { struct f2fs_dir_entry *de; unsigned long bit_pos = 0; struct f2fs_dentry_block *dentry_blk = kmap(dentry_page); const void *dentry_bits = &dentry_blk->dentry_bitmap; f2fs_hash_t namehash = f2fs_dentry_hash(name); int max_bits = *max_slots; int max_len = 0; while (bit_pos < NR_DENTRY_IN_BLOCK) { if (!test_bit_le(bit_pos, dentry_bits)) { *max_slots = 0; while (bit_pos < max_bits) { if (!test_bit_le(bit_pos, bitmap)) { if (bit_pos == 0) max_len = 1; else if (!test_bit_le(bit_pos - 1, dentry_bits)) else if (!test_bit_le(bit_pos - 1, bitmap)) max_len++; bit_pos++; continue; } de = &dentry_blk->dentry[bit_pos]; if (early_match_name(name->len, namehash, de)) { if (!memcmp(dentry_blk->filename[bit_pos], name->name, name->len)) { *res_page = dentry_page; de = &dentry[bit_pos]; if (early_match_name(name->len, namehash, de) && !memcmp(filenames[bit_pos], name->name, name->len)) goto found; } } if (max_len > *max_slots) { if (*max_slots >= 0 && max_len > *max_slots) { *max_slots = max_len; max_len = 0; } /* * For the most part, it should be a bug when name_len is zero. * We stop here for figuring out where the bugs has occurred. */ f2fs_bug_on(F2FS_P_SB(dentry_page), !de->name_len); /* remain bug on condition */ if (unlikely(!de->name_len)) *max_slots = -1; bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); } de = NULL; kunmap(dentry_page); found: if (max_len > *max_slots) *max_slots = max_len; Loading @@ -149,7 +169,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir, struct page *dentry_page; struct f2fs_dir_entry *de = NULL; bool room = false; int max_slots = 0; int max_slots; f2fs_bug_on(F2FS_I_SB(dir), level > MAX_DIR_HASH_DEPTH); Loading @@ -168,8 +188,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir, continue; } de = find_in_block(dentry_page, name, &max_slots, namehash, res_page); de = find_in_block(dentry_page, name, &max_slots, res_page); if (de) break; Loading fs/f2fs/f2fs.h +2 −1 Original line number Diff line number Diff line Loading @@ -1243,8 +1243,9 @@ struct dentry *f2fs_get_parent(struct dentry *child); * dir.c */ extern unsigned char f2fs_filetype_table[F2FS_FT_MAX]; bool early_match_name(size_t, f2fs_hash_t, struct f2fs_dir_entry *); void set_de_type(struct f2fs_dir_entry *, struct inode *); struct f2fs_dir_entry *find_target_dentry(struct qstr *, int *, const void *, struct f2fs_dir_entry *, __u8 (*)[F2FS_SLOT_LEN]); struct page *init_inode_metadata(struct inode *, struct inode *, const struct qstr *); void update_parent_metadata(struct inode *, struct inode *, unsigned int); Loading fs/f2fs/inline.c +17 −35 Original line number Diff line number Diff line Loading @@ -263,49 +263,31 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, struct qstr *name, struct page **res_page) { struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); struct page *ipage; struct f2fs_inline_dentry *inline_dentry; struct f2fs_dir_entry *de; f2fs_hash_t namehash; unsigned long bit_pos = 0; struct f2fs_inline_dentry *dentry_blk; const void *dentry_bits; struct page *ipage; int max_slots = NR_INLINE_DENTRY; ipage = get_node_page(sbi, dir->i_ino); if (IS_ERR(ipage)) return NULL; namehash = f2fs_dentry_hash(name); dentry_blk = inline_data_addr(ipage); dentry_bits = &dentry_blk->dentry_bitmap; inline_dentry = inline_data_addr(ipage); while (bit_pos < NR_INLINE_DENTRY) { if (!test_bit_le(bit_pos, dentry_bits)) { bit_pos++; continue; } de = &dentry_blk->dentry[bit_pos]; if (early_match_name(name->len, namehash, de)) { if (!memcmp(dentry_blk->filename[bit_pos], name->name, name->len)) { de = find_target_dentry(name, &max_slots, &inline_dentry->dentry_bitmap, inline_dentry->dentry, inline_dentry->filename); unlock_page(ipage); if (de) *res_page = ipage; goto found; } } else f2fs_put_page(ipage, 0); /* * For the most part, it should be a bug when name_len is zero. * We stop here for figuring out where the bugs are occurred. * We stop here for figuring out where the bugs has occurred. */ f2fs_bug_on(F2FS_P_SB(ipage), !de->name_len); bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); } de = NULL; found: unlock_page(ipage); f2fs_bug_on(sbi, max_slots < 0); return de; } Loading Loading
fs/f2fs/dir.c +46 −27 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ static unsigned long dir_block_index(unsigned int level, return bidx; } bool early_match_name(size_t namelen, f2fs_hash_t namehash, static bool early_match_name(size_t namelen, f2fs_hash_t namehash, struct f2fs_dir_entry *de) { if (le16_to_cpu(de->name_len) != namelen) Loading @@ -91,48 +91,68 @@ bool early_match_name(size_t namelen, f2fs_hash_t namehash, static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, struct qstr *name, int *max_slots, f2fs_hash_t namehash, struct page **res_page) struct page **res_page) { struct f2fs_dentry_block *dentry_blk; struct f2fs_dir_entry *de; *max_slots = NR_DENTRY_IN_BLOCK; dentry_blk = (struct f2fs_dentry_block *)kmap(dentry_page); de = find_target_dentry(name, max_slots, &dentry_blk->dentry_bitmap, dentry_blk->dentry, dentry_blk->filename); if (de) *res_page = dentry_page; else kunmap(dentry_page); /* * For the most part, it should be a bug when name_len is zero. * We stop here for figuring out where the bugs has occurred. */ f2fs_bug_on(F2FS_P_SB(dentry_page), *max_slots < 0); return de; } struct f2fs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots, const void *bitmap, struct f2fs_dir_entry *dentry, __u8 (*filenames)[F2FS_SLOT_LEN]) { struct f2fs_dir_entry *de; unsigned long bit_pos = 0; struct f2fs_dentry_block *dentry_blk = kmap(dentry_page); const void *dentry_bits = &dentry_blk->dentry_bitmap; f2fs_hash_t namehash = f2fs_dentry_hash(name); int max_bits = *max_slots; int max_len = 0; while (bit_pos < NR_DENTRY_IN_BLOCK) { if (!test_bit_le(bit_pos, dentry_bits)) { *max_slots = 0; while (bit_pos < max_bits) { if (!test_bit_le(bit_pos, bitmap)) { if (bit_pos == 0) max_len = 1; else if (!test_bit_le(bit_pos - 1, dentry_bits)) else if (!test_bit_le(bit_pos - 1, bitmap)) max_len++; bit_pos++; continue; } de = &dentry_blk->dentry[bit_pos]; if (early_match_name(name->len, namehash, de)) { if (!memcmp(dentry_blk->filename[bit_pos], name->name, name->len)) { *res_page = dentry_page; de = &dentry[bit_pos]; if (early_match_name(name->len, namehash, de) && !memcmp(filenames[bit_pos], name->name, name->len)) goto found; } } if (max_len > *max_slots) { if (*max_slots >= 0 && max_len > *max_slots) { *max_slots = max_len; max_len = 0; } /* * For the most part, it should be a bug when name_len is zero. * We stop here for figuring out where the bugs has occurred. */ f2fs_bug_on(F2FS_P_SB(dentry_page), !de->name_len); /* remain bug on condition */ if (unlikely(!de->name_len)) *max_slots = -1; bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); } de = NULL; kunmap(dentry_page); found: if (max_len > *max_slots) *max_slots = max_len; Loading @@ -149,7 +169,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir, struct page *dentry_page; struct f2fs_dir_entry *de = NULL; bool room = false; int max_slots = 0; int max_slots; f2fs_bug_on(F2FS_I_SB(dir), level > MAX_DIR_HASH_DEPTH); Loading @@ -168,8 +188,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir, continue; } de = find_in_block(dentry_page, name, &max_slots, namehash, res_page); de = find_in_block(dentry_page, name, &max_slots, res_page); if (de) break; Loading
fs/f2fs/f2fs.h +2 −1 Original line number Diff line number Diff line Loading @@ -1243,8 +1243,9 @@ struct dentry *f2fs_get_parent(struct dentry *child); * dir.c */ extern unsigned char f2fs_filetype_table[F2FS_FT_MAX]; bool early_match_name(size_t, f2fs_hash_t, struct f2fs_dir_entry *); void set_de_type(struct f2fs_dir_entry *, struct inode *); struct f2fs_dir_entry *find_target_dentry(struct qstr *, int *, const void *, struct f2fs_dir_entry *, __u8 (*)[F2FS_SLOT_LEN]); struct page *init_inode_metadata(struct inode *, struct inode *, const struct qstr *); void update_parent_metadata(struct inode *, struct inode *, unsigned int); Loading
fs/f2fs/inline.c +17 −35 Original line number Diff line number Diff line Loading @@ -263,49 +263,31 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, struct qstr *name, struct page **res_page) { struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); struct page *ipage; struct f2fs_inline_dentry *inline_dentry; struct f2fs_dir_entry *de; f2fs_hash_t namehash; unsigned long bit_pos = 0; struct f2fs_inline_dentry *dentry_blk; const void *dentry_bits; struct page *ipage; int max_slots = NR_INLINE_DENTRY; ipage = get_node_page(sbi, dir->i_ino); if (IS_ERR(ipage)) return NULL; namehash = f2fs_dentry_hash(name); dentry_blk = inline_data_addr(ipage); dentry_bits = &dentry_blk->dentry_bitmap; inline_dentry = inline_data_addr(ipage); while (bit_pos < NR_INLINE_DENTRY) { if (!test_bit_le(bit_pos, dentry_bits)) { bit_pos++; continue; } de = &dentry_blk->dentry[bit_pos]; if (early_match_name(name->len, namehash, de)) { if (!memcmp(dentry_blk->filename[bit_pos], name->name, name->len)) { de = find_target_dentry(name, &max_slots, &inline_dentry->dentry_bitmap, inline_dentry->dentry, inline_dentry->filename); unlock_page(ipage); if (de) *res_page = ipage; goto found; } } else f2fs_put_page(ipage, 0); /* * For the most part, it should be a bug when name_len is zero. * We stop here for figuring out where the bugs are occurred. * We stop here for figuring out where the bugs has occurred. */ f2fs_bug_on(F2FS_P_SB(ipage), !de->name_len); bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); } de = NULL; found: unlock_page(ipage); f2fs_bug_on(sbi, max_slots < 0); return de; } Loading