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.

Signed-off-by: Tetsuhiro Kohada <kohada...@gmail.com>
---
Changes in v2
 - Add error check when extracting name
 - Remove temporary exfat_get_dentry_set() with ES_2_ENTRIES
 - Remove duplicate parts in commit message
Changes in v3:
 - Nothing
Changes in v4:
 - Into patch series '[PATCH v4] exfat: integrates dir-entry getting and 
validation'

 fs/exfat/dir.c      | 156 +++++++++-----------------------------------
 fs/exfat/exfat_fs.h |   2 +-
 fs/exfat/namei.c    |   4 +-
 3 files changed, 32 insertions(+), 130 deletions(-)

diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
index 99d9e6d119d6..cd37091844fa 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)
 {
@@ -871,13 +853,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
@@ -887,13 +862,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;
@@ -911,27 +885,34 @@ 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;
+                       bool found;
 
                        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) {
@@ -956,7 +937,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;
@@ -965,80 +945,30 @@ 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_ALL_ENTRIES);
+                       if (!es)
                                continue;
-                       }
 
-                       brelse(bh);
-                       if (entry_type == TYPE_NAME) {
-                               unsigned short entry_uniname[16], unichar;
+                       num_ext = ES_FILE(es).num_ext;
+                       name_hash = le16_to_cpu(ES_STREAM(es).name_hash);
+                       name_len = ES_STREAM(es).name_len;
 
-                               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;
-
-                               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;
-                               }
+                       found = p_uniname->name_hash == name_hash &&
+                               p_uniname->name_len == name_len &&
+                               !exfat_get_uniname_from_name_entries(es, 
&uni_name) &&
+                               !exfat_uniname_ncmp(sb, p_uniname->name, 
uni_name.name, name_len);
 
-                               *(uniname+len) = unichar;
-                               continue;
-                       }
+                       exfat_free_dentry_set(es, false);
 
-                       if (entry_type &
-                                       (TYPE_CRITICAL_SEC | TYPE_BENIGN_SEC)) {
-                               if (step == DIRENT_STEP_SECD) {
-                                       if (++order == num_ext)
-                                               goto found;
-                                       continue;
-                               }
+                       if (found) {
+                               /* 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) {
@@ -1071,32 +1001,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 e46f3e0c16b7..7057e64b405d 100644
--- a/fs/exfat/exfat_fs.h
+++ b/fs/exfat/exfat_fs.h
@@ -458,7 +458,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 6a034f504d83..d2b9044d0b31 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

Reply via email to