summaryrefslogtreecommitdiff
path: root/fs/exfat/namei.c
diff options
context:
space:
mode:
authorYuezhang Mo <Yuezhang.Mo@sony.com>2024-09-12 16:57:06 +0800
committerNamjae Jeon <linkinjeon@kernel.org>2024-11-25 17:08:27 +0900
commit8a3f5711ad74db9881b289a6e34d7f3b700df720 (patch)
tree921c983ed0f0581900e725a6967c29fdf458f502 /fs/exfat/namei.c
parent6b151eb5df78dc1a1ea7c862834199e08ea11c7b (diff)
exfat: reduce FAT chain traversal
Before this commit, ->dir and ->entry of exfat_inode_info record the first cluster of the parent directory and the directory entry index starting from this cluster. The directory entry set will be gotten during write-back-inode/rmdir/ unlink/rename. If the clusters of the parent directory are not continuous, the FAT chain will be traversed from the first cluster of the parent directory to find the cluster where ->entry is located. After this commit, ->dir records the cluster where the first directory entry in the directory entry set is located, and ->entry records the directory entry index in the cluster, so that there is almost no need to access the FAT when getting the directory entry set. Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com> Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com> Reviewed-by: Daniel Palmer <daniel.palmer@sony.com> Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Diffstat (limited to 'fs/exfat/namei.c')
-rw-r--r--fs/exfat/namei.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
index 8138ed61c1b2..97d2774760fe 100644
--- a/fs/exfat/namei.c
+++ b/fs/exfat/namei.c
@@ -288,8 +288,22 @@ static int exfat_check_max_dentries(struct inode *inode)
return 0;
}
-/* find empty directory entry.
- * if there isn't any empty slot, expand cluster chain.
+/*
+ * Find an empty directory entry set.
+ *
+ * If there isn't any empty slot, expand cluster chain.
+ *
+ * in:
+ * inode: inode of the parent directory
+ * num_entries: specifies how many dentries in the empty directory entry set
+ *
+ * out:
+ * p_dir: the cluster where the empty directory entry set is located
+ * es: The found empty directory entry set
+ *
+ * return:
+ * the directory entry index in p_dir is returned on succeeds
+ * -error code is returned on failure
*/
static int exfat_find_empty_entry(struct inode *inode,
struct exfat_chain *p_dir, int num_entries,
@@ -381,7 +395,10 @@ static int exfat_find_empty_entry(struct inode *inode,
inode->i_blocks += sbi->cluster_size >> 9;
}
- return dentry;
+ p_dir->dir = exfat_sector_to_cluster(sbi, es->bh[0]->b_blocknr);
+ p_dir->size -= dentry / sbi->dentries_per_clu;
+
+ return dentry & (sbi->dentries_per_clu - 1);
}
/*
@@ -613,15 +630,16 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
if (dentry < 0)
return dentry; /* -error value */
- info->dir = cdir;
- 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;
+
+ info->dir = cdir;
+ info->entry = dentry;
+ info->num_subdirs = 0;
+
if (exfat_get_dentry_set(&es, sb, &cdir, dentry, ES_2_ENTRIES))
return -EIO;
ep = exfat_get_dentry_cached(&es, ES_IDX_FILE);