Name extraction in exfat_find_dir_entry() also doesn't care NameLength, so the name may be incorrect. Replace the name extraction in exfat_find_dir_entry() with using exfat_entry_set_cache and exfat_get_uniname_from_name_entries(), like exfat_readdir(). Replace the name extraction with using exfat_entry_set_cache and exfat_get_uniname_from_name_entries(), like exfat_readdir(). And, remove unused functions/parameters. ** This patch depends on: '[PATCH v3] exfat: integrates dir-entry getting and validation'. Signed-off-by: Tetsuhiro Kohada <kohada.t2@xxxxxxxxx> --- fs/exfat/dir.c | 161 ++++++++++---------------------------------- fs/exfat/exfat_fs.h | 2 +- fs/exfat/namei.c | 4 +- 3 files changed, 38 insertions(+), 129 deletions(-) diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c index 545bb73b95e9..c9715c7a55a1 100644 --- a/fs/exfat/dir.c +++ b/fs/exfat/dir.c @@ -10,24 +10,6 @@ #include "exfat_raw.h" #include "exfat_fs.h" -static int exfat_extract_uni_name(struct exfat_dentry *ep, - unsigned short *uniname) -{ - int i, len = 0; - - for (i = 0; i < EXFAT_FILE_NAME_LEN; i++) { - *uniname = le16_to_cpu(ep->dentry.name.unicode_0_14[i]); - if (*uniname == 0x0) - return len; - uniname++; - len++; - } - - *uniname = 0x0; - return len; - -} - static int exfat_get_uniname_from_name_entries(struct exfat_entry_set_cache *es, struct exfat_uni_name *uniname) { @@ -869,13 +851,6 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, return NULL; } -enum { - DIRENT_STEP_FILE, - DIRENT_STEP_STRM, - DIRENT_STEP_NAME, - DIRENT_STEP_SECD, -}; - /* * return values: * >= 0 : return dir entiry position with the name in dir @@ -885,13 +860,12 @@ enum { */ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname, - int num_entries, unsigned int type) + int num_entries) { - int i, rewind = 0, dentry = 0, end_eidx = 0, num_ext = 0, len; - int order, step, name_len = 0; + int i, rewind = 0, dentry = 0, end_eidx = 0, num_ext = 0; + int name_len = 0; int dentries_per_clu, num_empty = 0; unsigned int entry_type; - unsigned short *uniname = NULL; struct exfat_chain clu; struct exfat_hint *hint_stat = &ei->hint_stat; struct exfat_hint_femp candi_empty; @@ -909,27 +883,33 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, candi_empty.eidx = EXFAT_HINT_NONE; rewind: - order = 0; - step = DIRENT_STEP_FILE; while (clu.dir != EXFAT_EOF_CLUSTER) { i = dentry & (dentries_per_clu - 1); for (; i < dentries_per_clu; i++, dentry++) { struct exfat_dentry *ep; struct buffer_head *bh; + struct exfat_entry_set_cache *es; + struct exfat_uni_name uni_name; + u16 name_hash; if (rewind && dentry == end_eidx) goto not_found; + /* skip secondary dir-entries in previous dir-entry set */ + if (num_ext) { + num_ext--; + continue; + } + ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); if (!ep) return -EIO; entry_type = exfat_get_entry_type(ep); + brelse(bh); if (entry_type == TYPE_UNUSED || entry_type == TYPE_DELETED) { - step = DIRENT_STEP_FILE; - num_empty++; if (candi_empty.eidx == EXFAT_HINT_NONE && num_empty == 1) { @@ -954,7 +934,6 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, } } - brelse(bh); if (entry_type == TYPE_UNUSED) goto not_found; continue; @@ -963,80 +942,38 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, num_empty = 0; candi_empty.eidx = EXFAT_HINT_NONE; - if (entry_type == TYPE_FILE || entry_type == TYPE_DIR) { - step = DIRENT_STEP_FILE; - if (type == TYPE_ALL || type == entry_type) { - num_ext = ep->dentry.file.num_ext; - step = DIRENT_STEP_STRM; - } - brelse(bh); + if (entry_type != TYPE_FILE && entry_type != TYPE_DIR) continue; - } - - if (entry_type == TYPE_STREAM) { - u16 name_hash; - if (step != DIRENT_STEP_STRM) { - step = DIRENT_STEP_FILE; - brelse(bh); - continue; - } - step = DIRENT_STEP_FILE; - name_hash = le16_to_cpu( - ep->dentry.stream.name_hash); - if (p_uniname->name_hash == name_hash && - p_uniname->name_len == - ep->dentry.stream.name_len) { - step = DIRENT_STEP_NAME; - order = 1; - name_len = 0; - } - brelse(bh); + es = exfat_get_dentry_set(sb, &ei->dir, dentry, ES_2_ENTRIES); + if (!es) continue; - } - brelse(bh); - if (entry_type == TYPE_NAME) { - unsigned short entry_uniname[16], unichar; - - if (step != DIRENT_STEP_NAME) { - step = DIRENT_STEP_FILE; - continue; - } - - if (++order == 2) - uniname = p_uniname->name; - else - uniname += EXFAT_FILE_NAME_LEN; - - len = exfat_extract_uni_name(ep, entry_uniname); - name_len += len; - - unichar = *(uniname+len); - *(uniname+len) = 0x0; + num_ext = es->de_file->num_ext; + name_hash = le16_to_cpu(es->de_stream->name_hash); + name_len = es->de_stream->name_len; + exfat_free_dentry_set(es, false); - if (exfat_uniname_ncmp(sb, uniname, - entry_uniname, len)) { - step = DIRENT_STEP_FILE; - } else if (p_uniname->name_len == name_len) { - if (order == num_ext) - goto found; - step = DIRENT_STEP_SECD; - } + if (p_uniname->name_hash != name_hash || + p_uniname->name_len != name_len) + continue; - *(uniname+len) = unichar; + es = exfat_get_dentry_set(sb, &ei->dir, dentry, ES_ALL_ENTRIES); + if (!es) continue; - } - if (entry_type & - (TYPE_CRITICAL_SEC | TYPE_BENIGN_SEC)) { - if (step == DIRENT_STEP_SECD) { - if (++order == num_ext) - goto found; - continue; - } + exfat_get_uniname_from_name_entries(es, &uni_name); + exfat_free_dentry_set(es, false); + + if (!exfat_uniname_ncmp(sb, + p_uniname->name, + uni_name.name, + name_len)) { + /* set the last used position as hint */ + hint_stat->clu = clu.dir; + hint_stat->eidx = dentry; + return dentry; } - step = DIRENT_STEP_FILE; } if (clu.flags == ALLOC_NO_FAT_CHAIN) { @@ -1069,32 +1006,6 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, hint_stat->clu = p_dir->dir; hint_stat->eidx = 0; return -ENOENT; - -found: - /* next dentry we'll find is out of this cluster */ - if (!((dentry + 1) & (dentries_per_clu - 1))) { - int ret = 0; - - if (clu.flags == ALLOC_NO_FAT_CHAIN) { - if (--clu.size > 0) - clu.dir++; - else - clu.dir = EXFAT_EOF_CLUSTER; - } else { - ret = exfat_get_next_cluster(sb, &clu.dir); - } - - if (ret || clu.dir == EXFAT_EOF_CLUSTER) { - /* just initialized hint_stat */ - hint_stat->clu = p_dir->dir; - hint_stat->eidx = 0; - return (dentry - num_ext); - } - } - - hint_stat->clu = clu.dir; - hint_stat->eidx = dentry + 1; - return dentry - num_ext; } int exfat_count_ext_entries(struct super_block *sb, struct exfat_chain *p_dir, diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h index b88b7abc25bd..62a4768a4f6e 100644 --- a/fs/exfat/exfat_fs.h +++ b/fs/exfat/exfat_fs.h @@ -456,7 +456,7 @@ void exfat_update_dir_chksum_with_entry_set(struct exfat_entry_set_cache *es); int exfat_calc_num_entries(struct exfat_uni_name *p_uniname); int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname, - int num_entries, unsigned int type); + int num_entries); int exfat_alloc_new_dir(struct inode *inode, struct exfat_chain *clu); int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir, int entry, sector_t *sector, int *offset); diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c index a65d60ef93f4..c59d523547ca 100644 --- a/fs/exfat/namei.c +++ b/fs/exfat/namei.c @@ -625,9 +625,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname, } /* search the file name for directories */ - dentry = exfat_find_dir_entry(sb, ei, &cdir, &uni_name, - num_entries, TYPE_ALL); - + dentry = exfat_find_dir_entry(sb, ei, &cdir, &uni_name, num_entries); if ((dentry < 0) && (dentry != -EEXIST)) return dentry; /* -error value */ -- 2.25.1