exfat: convert exfat_init_ext_entry() to use dentry cache
authorYuezhang Mo <Yuezhang.Mo@sony.com>
Fri, 5 Aug 2022 08:42:02 +0000 (16:42 +0800)
committerNamjae Jeon <linkinjeon@kernel.org>
Tue, 19 Mar 2024 11:55:49 +0000 (20:55 +0900)
Before this conversion, in exfat_init_ext_entry(), to init
the dentries in a dentry set, the sync times is equals the
dentry number if 'dirsync' or 'sync' is enabled.
That affects not only performance but also device life.

After this conversion, only needs to be synchronized once if
'dirsync' or 'sync' is enabled.

Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: Andy Wu <Andy.Wu@sony.com>
Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
fs/exfat/dir.c
fs/exfat/exfat_fs.h
fs/exfat/namei.c

index 0008d4681d293ef104fd7d1d44c6890fcd86c817..df39e245671dcd55a91da4a57d87d45b12b88f1d 100644 (file)
@@ -532,46 +532,27 @@ static void exfat_free_benign_secondary_clusters(struct inode *inode,
        exfat_free_cluster(inode, &dir);
 }
 
-int exfat_init_ext_entry(struct inode *inode, struct exfat_chain *p_dir,
-               int entry, int num_entries, struct exfat_uni_name *p_uniname)
+void exfat_init_ext_entry(struct exfat_entry_set_cache *es, int num_entries,
+               struct exfat_uni_name *p_uniname)
 {
-       struct super_block *sb = inode->i_sb;
        int i;
        unsigned short *uniname = p_uniname->name;
        struct exfat_dentry *ep;
-       struct buffer_head *bh;
-       int sync = IS_DIRSYNC(inode);
-
-       ep = exfat_get_dentry(sb, p_dir, entry, &bh);
-       if (!ep)
-               return -EIO;
 
+       ep = exfat_get_dentry_cached(es, ES_IDX_FILE);
        ep->dentry.file.num_ext = (unsigned char)(num_entries - 1);
-       exfat_update_bh(bh, sync);
-       brelse(bh);
-
-       ep = exfat_get_dentry(sb, p_dir, entry + 1, &bh);
-       if (!ep)
-               return -EIO;
 
+       ep = exfat_get_dentry_cached(es, ES_IDX_STREAM);
        ep->dentry.stream.name_len = p_uniname->name_len;
        ep->dentry.stream.name_hash = cpu_to_le16(p_uniname->name_hash);
-       exfat_update_bh(bh, sync);
-       brelse(bh);
-
-       for (i = EXFAT_FIRST_CLUSTER; i < num_entries; i++) {
-               ep = exfat_get_dentry(sb, p_dir, entry + i, &bh);
-               if (!ep)
-                       return -EIO;
 
+       for (i = ES_IDX_FIRST_FILENAME; i < num_entries; i++) {
+               ep = exfat_get_dentry_cached(es, i);
                exfat_init_name_entry(ep, uniname);
-               exfat_update_bh(bh, sync);
-               brelse(bh);
                uniname += EXFAT_FILE_NAME_LEN;
        }
 
-       exfat_update_dir_chksum(inode, p_dir, entry);
-       return 0;
+       exfat_update_dir_chksum_with_entry_set(es);
 }
 
 void exfat_remove_entries(struct inode *inode, struct exfat_entry_set_cache *es,
index 83ae84a657cdb96e5f93a24a6017e2fde7a2ae45..1cc91476b9c5455799318113da118a54e13d3c5d 100644 (file)
@@ -483,8 +483,8 @@ unsigned int exfat_get_entry_type(struct exfat_dentry *p_entry);
 void exfat_init_dir_entry(struct exfat_entry_set_cache *es,
                unsigned int type, unsigned int start_clu,
                unsigned long long size, struct timespec64 *ts);
-int exfat_init_ext_entry(struct inode *inode, struct exfat_chain *p_dir,
-               int entry, int num_entries, struct exfat_uni_name *p_uniname);
+void exfat_init_ext_entry(struct exfat_entry_set_cache *es, int num_entries,
+               struct exfat_uni_name *p_uniname);
 void exfat_remove_entries(struct inode *inode, struct exfat_entry_set_cache *es,
                int order);
 int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir,
index be6760297e8fa94407854a231cf4a55f21201f22..2c6df4f966f513ae624252d780b77d986f324803 100644 (file)
@@ -539,15 +539,12 @@ static int exfat_add_entry(struct inode *inode, const char *path,
                goto out;
 
        exfat_init_dir_entry(&es, type, start_clu, clu_size, &ts);
+       exfat_init_ext_entry(&es, num_entries, &uniname);
 
        ret = exfat_put_dentry_set(&es, IS_DIRSYNC(inode));
        if (ret)
                goto out;
 
-       ret = exfat_init_ext_entry(inode, p_dir, dentry, num_entries, &uniname);
-       if (ret)
-               goto out;
-
        info->dir = *p_dir;
        info->entry = dentry;
        info->flags = ALLOC_NO_FAT_CHAIN;
@@ -1018,8 +1015,7 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
        int ret, num_new_entries;
        struct exfat_dentry *epold, *epnew;
        struct super_block *sb = inode->i_sb;
-       struct buffer_head *new_bh;
-       struct exfat_entry_set_cache old_es;
+       struct exfat_entry_set_cache old_es, new_es;
        int sync = IS_DIRSYNC(inode);
 
        num_new_entries = exfat_calc_num_entries(p_uniname);
@@ -1044,33 +1040,25 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
                        goto put_old_es;
                }
 
-               epnew = exfat_get_dentry(sb, p_dir, newentry, &new_bh);
-               if (!epnew) {
-                       ret = -EIO;
+               ret = exfat_get_empty_dentry_set(&new_es, sb, p_dir, newentry,
+                               num_new_entries);
+               if (ret)
                        goto put_old_es;
-               }
 
+               epnew = exfat_get_dentry_cached(&new_es, ES_IDX_FILE);
                *epnew = *epold;
                if (exfat_get_entry_type(epnew) == TYPE_FILE) {
                        epnew->dentry.file.attr |= cpu_to_le16(EXFAT_ATTR_ARCHIVE);
                        ei->attr |= EXFAT_ATTR_ARCHIVE;
                }
-               exfat_update_bh(new_bh, sync);
-               brelse(new_bh);
 
                epold = exfat_get_dentry_cached(&old_es, ES_IDX_STREAM);
-               epnew = exfat_get_dentry(sb, p_dir, newentry + 1, &new_bh);
-               if (!epnew) {
-                       ret = -EIO;
-                       goto put_old_es;
-               }
-
+               epnew = exfat_get_dentry_cached(&new_es, ES_IDX_STREAM);
                *epnew = *epold;
-               exfat_update_bh(new_bh, sync);
-               brelse(new_bh);
 
-               ret = exfat_init_ext_entry(inode, p_dir, newentry,
-                       num_new_entries, p_uniname);
+               exfat_init_ext_entry(&new_es, num_new_entries, p_uniname);
+
+               ret = exfat_put_dentry_set(&new_es, sync);
                if (ret)
                        goto put_old_es;
 
@@ -1084,11 +1072,7 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
                }
 
                exfat_remove_entries(inode, &old_es, ES_IDX_FIRST_FILENAME + 1);
-
-               ret = exfat_init_ext_entry(inode, p_dir, oldentry,
-                       num_new_entries, p_uniname);
-               if (ret)
-                       goto put_old_es;
+               exfat_init_ext_entry(&old_es, num_new_entries, p_uniname);
        }
        return exfat_put_dentry_set(&old_es, sync);
 
@@ -1104,8 +1088,7 @@ static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
        int ret, newentry, num_new_entries;
        struct exfat_dentry *epmov, *epnew;
        struct super_block *sb = inode->i_sb;
-       struct buffer_head *new_bh;
-       struct exfat_entry_set_cache mov_es;
+       struct exfat_entry_set_cache mov_es, new_es;
 
        num_new_entries = exfat_calc_num_entries(p_uniname);
        if (num_new_entries < 0)
@@ -1120,43 +1103,35 @@ static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
        if (ret)
                return -EIO;
 
-       epmov = exfat_get_dentry_cached(&mov_es, ES_IDX_FILE);
-       epnew = exfat_get_dentry(sb, p_newdir, newentry, &new_bh);
-       if (!epnew) {
-               ret = -EIO;
+       ret = exfat_get_empty_dentry_set(&new_es, sb, p_newdir, newentry,
+                       num_new_entries);
+       if (ret)
                goto put_mov_es;
-       }
 
+       epmov = exfat_get_dentry_cached(&mov_es, ES_IDX_FILE);
+       epnew = exfat_get_dentry_cached(&new_es, ES_IDX_FILE);
        *epnew = *epmov;
        if (exfat_get_entry_type(epnew) == TYPE_FILE) {
                epnew->dentry.file.attr |= cpu_to_le16(EXFAT_ATTR_ARCHIVE);
                ei->attr |= EXFAT_ATTR_ARCHIVE;
        }
-       exfat_update_bh(new_bh, IS_DIRSYNC(inode));
-       brelse(new_bh);
 
        epmov = exfat_get_dentry_cached(&mov_es, ES_IDX_STREAM);
-       epnew = exfat_get_dentry(sb, p_newdir, newentry + 1, &new_bh);
-       if (!epnew) {
-               ret = -EIO;
-               goto put_mov_es;
-       }
-
+       epnew = exfat_get_dentry_cached(&new_es, ES_IDX_STREAM);
        *epnew = *epmov;
-       exfat_update_bh(new_bh, IS_DIRSYNC(inode));
-       brelse(new_bh);
-
-       ret = exfat_init_ext_entry(inode, p_newdir, newentry, num_new_entries,
-               p_uniname);
-       if (ret)
-               return ret;
 
+       exfat_init_ext_entry(&new_es, num_new_entries, p_uniname);
        exfat_remove_entries(inode, &mov_es, ES_IDX_FILE);
 
        exfat_chain_set(&ei->dir, p_newdir->dir, p_newdir->size,
                p_newdir->flags);
 
        ei->entry = newentry;
+
+       ret = exfat_put_dentry_set(&new_es, IS_DIRSYNC(inode));
+       if (ret)
+               goto put_mov_es;
+
        return exfat_put_dentry_set(&mov_es, IS_DIRSYNC(inode));
 
 put_mov_es: