aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exfat/namei.c
diff options
context:
space:
mode:
authorHyeongseok Kim <hyeongseok@gmail.com>2021-03-22 12:53:36 +0900
committerNamjae Jeon <namjae.jeon@samsung.com>2021-04-27 20:45:07 +0900
commitc6e2f52e3051e8d898d38840104638ca8bbcdec2 (patch)
tree8eb871698cb312d75d7fb56ab582b7ddb133b102 /fs/exfat/namei.c
parentexfat: improve write performance when dirsync enabled (diff)
downloadlinux-dev-c6e2f52e3051e8d898d38840104638ca8bbcdec2.tar.xz
linux-dev-c6e2f52e3051e8d898d38840104638ca8bbcdec2.zip
exfat: speed up iterate/lookup by fixing start point of traversing cluster chain
When directory iterate and lookup is called, there's a buggy rewinding of start point for traversing cluster chain to the parent directory entry's first cluster. This caused repeated cluster chain traversing from the first entry of the parent directory that would show worse performance if huge amounts of files exist under the parent directory. Fix not to rewind, make continue from currently referenced cluster and dir entry. Tested with 50,000 files under single directory / 256GB sdcard, with command "time ls -l > /dev/null", Before : 0m08.69s real 0m00.27s user 0m05.91s system After : 0m07.01s real 0m00.25s user 0m04.34s system Signed-off-by: Hyeongseok Kim <hyeongseok@gmail.com> Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com> Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Diffstat (limited to 'fs/exfat/namei.c')
-rw-r--r--fs/exfat/namei.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
index 1f7b3dc66fcd..24b41103d1cc 100644
--- a/fs/exfat/namei.c
+++ b/fs/exfat/namei.c
@@ -596,6 +596,8 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
struct exfat_inode_info *ei = EXFAT_I(dir);
struct exfat_dentry *ep, *ep2;
struct exfat_entry_set_cache *es;
+ /* for optimized dir & entry to prevent long traverse of cluster chain */
+ struct exfat_hint hint_opt;
if (qname->len == 0)
return -ENOENT;
@@ -619,7 +621,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);
+ num_entries, TYPE_ALL, &hint_opt);
if (dentry < 0)
return dentry; /* -error value */
@@ -628,6 +630,11 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
info->entry = dentry;
info->num_subdirs = 0;
+ /* adjust cdir to the optimized value */
+ cdir.dir = hint_opt.clu;
+ if (cdir.flags & ALLOC_NO_FAT_CHAIN)
+ cdir.size -= dentry / sbi->dentries_per_clu;
+ dentry = hint_opt.eidx;
es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES);
if (!es)
return -EIO;