Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit ff4343d

Browse files
YuezhangMonamjaejeon
authored andcommitted
exfat: convert exfat_remove_entries() to use dentry cache
Before this conversion, in exfat_remove_entries(), to mark the dentries in a dentry set as deleted, the sync times is equals the dentry numbers 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 <[email protected]> Reviewed-by: Andy Wu <[email protected]> Reviewed-by: Aoyama Wataru <[email protected]> Reviewed-by: Sungjong Seo <[email protected]> Signed-off-by: Namjae Jeon <[email protected]>
1 parent cf8663f commit ff4343d

File tree

3 files changed

+90
-115
lines changed

3 files changed

+90
-115
lines changed

fs/exfat/dir.c

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -577,28 +577,23 @@ int exfat_init_ext_entry(struct inode *inode, struct exfat_chain *p_dir,
577577
return 0;
578578
}
579579

580-
int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir,
581-
int entry, int order, int num_entries)
580+
void exfat_remove_entries(struct inode *inode, struct exfat_entry_set_cache *es,
581+
int order)
582582
{
583-
struct super_block *sb = inode->i_sb;
584583
int i;
585584
struct exfat_dentry *ep;
586-
struct buffer_head *bh;
587585

588-
for (i = order; i < num_entries; i++) {
589-
ep = exfat_get_dentry(sb, p_dir, entry + i, &bh);
590-
if (!ep)
591-
return -EIO;
586+
for (i = order; i < es->num_entries; i++) {
587+
ep = exfat_get_dentry_cached(es, i);
592588

593589
if (exfat_get_entry_type(ep) & TYPE_BENIGN_SEC)
594590
exfat_free_benign_secondary_clusters(inode, ep);
595591

596592
exfat_set_entry_type(ep, TYPE_DELETED);
597-
exfat_update_bh(bh, IS_DIRSYNC(inode));
598-
brelse(bh);
599593
}
600594

601-
return 0;
595+
if (order < es->num_entries)
596+
es->modified = true;
602597
}
603598

604599
void exfat_update_dir_chksum_with_entry_set(struct exfat_entry_set_cache *es)

fs/exfat/exfat_fs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,8 @@ void exfat_init_dir_entry(struct exfat_entry_set_cache *es,
485485
unsigned long long size, struct timespec64 *ts);
486486
int exfat_init_ext_entry(struct inode *inode, struct exfat_chain *p_dir,
487487
int entry, int num_entries, struct exfat_uni_name *p_uniname);
488-
int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir,
489-
int entry, int order, int num_entries);
488+
void exfat_remove_entries(struct inode *inode, struct exfat_entry_set_cache *es,
489+
int order);
490490
int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir,
491491
int entry);
492492
void exfat_update_dir_chksum_with_entry_set(struct exfat_entry_set_cache *es);

fs/exfat/namei.c

Lines changed: 82 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -803,12 +803,11 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
803803
static int exfat_unlink(struct inode *dir, struct dentry *dentry)
804804
{
805805
struct exfat_chain cdir;
806-
struct exfat_dentry *ep;
807806
struct super_block *sb = dir->i_sb;
808807
struct inode *inode = dentry->d_inode;
809808
struct exfat_inode_info *ei = EXFAT_I(inode);
810-
struct buffer_head *bh;
811-
int num_entries, entry, err = 0;
809+
struct exfat_entry_set_cache es;
810+
int entry, err = 0;
812811

813812
mutex_lock(&EXFAT_SB(sb)->s_lock);
814813
exfat_chain_dup(&cdir, &ei->dir);
@@ -819,26 +818,20 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
819818
goto unlock;
820819
}
821820

822-
ep = exfat_get_dentry(sb, &cdir, entry, &bh);
823-
if (!ep) {
824-
err = -EIO;
825-
goto unlock;
826-
}
827-
num_entries = exfat_count_ext_entries(sb, &cdir, entry, ep);
828-
if (num_entries < 0) {
821+
err = exfat_get_dentry_set(&es, sb, &cdir, entry, ES_ALL_ENTRIES);
822+
if (err) {
829823
err = -EIO;
830-
brelse(bh);
831824
goto unlock;
832825
}
833-
num_entries++;
834-
brelse(bh);
835826

836827
exfat_set_volume_dirty(sb);
828+
837829
/* update the directory entry */
838-
if (exfat_remove_entries(dir, &cdir, entry, 0, num_entries)) {
839-
err = -EIO;
830+
exfat_remove_entries(inode, &es, ES_IDX_FILE);
831+
832+
err = exfat_put_dentry_set(&es, IS_DIRSYNC(inode));
833+
if (err)
840834
goto unlock;
841-
}
842835

843836
/* This doesn't modify ei */
844837
ei->dir.dir = DIR_DELETED;
@@ -954,13 +947,12 @@ static int exfat_check_dir_empty(struct super_block *sb,
954947
static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
955948
{
956949
struct inode *inode = dentry->d_inode;
957-
struct exfat_dentry *ep;
958950
struct exfat_chain cdir, clu_to_free;
959951
struct super_block *sb = inode->i_sb;
960952
struct exfat_sb_info *sbi = EXFAT_SB(sb);
961953
struct exfat_inode_info *ei = EXFAT_I(inode);
962-
struct buffer_head *bh;
963-
int num_entries, entry, err;
954+
struct exfat_entry_set_cache es;
955+
int entry, err;
964956

965957
mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock);
966958

@@ -984,27 +976,20 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
984976
goto unlock;
985977
}
986978

987-
ep = exfat_get_dentry(sb, &cdir, entry, &bh);
988-
if (!ep) {
989-
err = -EIO;
990-
goto unlock;
991-
}
992-
993-
num_entries = exfat_count_ext_entries(sb, &cdir, entry, ep);
994-
if (num_entries < 0) {
979+
err = exfat_get_dentry_set(&es, sb, &cdir, entry, ES_ALL_ENTRIES);
980+
if (err) {
995981
err = -EIO;
996-
brelse(bh);
997982
goto unlock;
998983
}
999-
num_entries++;
1000-
brelse(bh);
1001984

1002985
exfat_set_volume_dirty(sb);
1003-
err = exfat_remove_entries(dir, &cdir, entry, 0, num_entries);
1004-
if (err) {
1005-
exfat_err(sb, "failed to exfat_remove_entries : err(%d)", err);
986+
987+
exfat_remove_entries(inode, &es, ES_IDX_FILE);
988+
989+
err = exfat_put_dentry_set(&es, IS_DIRSYNC(dir));
990+
if (err)
1006991
goto unlock;
1007-
}
992+
1008993
ei->dir.dir = DIR_DELETED;
1009994

1010995
inode_inc_iversion(dir);
@@ -1030,105 +1015,96 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
10301015
int oldentry, struct exfat_uni_name *p_uniname,
10311016
struct exfat_inode_info *ei)
10321017
{
1033-
int ret, num_old_entries, num_new_entries;
1018+
int ret, num_new_entries;
10341019
struct exfat_dentry *epold, *epnew;
10351020
struct super_block *sb = inode->i_sb;
1036-
struct buffer_head *new_bh, *old_bh;
1021+
struct buffer_head *new_bh;
1022+
struct exfat_entry_set_cache old_es;
10371023
int sync = IS_DIRSYNC(inode);
10381024

1039-
epold = exfat_get_dentry(sb, p_dir, oldentry, &old_bh);
1040-
if (!epold)
1041-
return -EIO;
1042-
1043-
num_old_entries = exfat_count_ext_entries(sb, p_dir, oldentry, epold);
1044-
if (num_old_entries < 0)
1045-
return -EIO;
1046-
num_old_entries++;
1047-
10481025
num_new_entries = exfat_calc_num_entries(p_uniname);
10491026
if (num_new_entries < 0)
10501027
return num_new_entries;
10511028

1052-
if (num_old_entries < num_new_entries) {
1029+
ret = exfat_get_dentry_set(&old_es, sb, p_dir, oldentry, ES_ALL_ENTRIES);
1030+
if (ret) {
1031+
ret = -EIO;
1032+
return ret;
1033+
}
1034+
1035+
epold = exfat_get_dentry_cached(&old_es, ES_IDX_FILE);
1036+
1037+
if (old_es.num_entries < num_new_entries) {
10531038
int newentry;
10541039

10551040
newentry =
10561041
exfat_find_empty_entry(inode, p_dir, num_new_entries);
1057-
if (newentry < 0)
1058-
return newentry; /* -EIO or -ENOSPC */
1042+
if (newentry < 0) {
1043+
ret = newentry; /* -EIO or -ENOSPC */
1044+
goto put_old_es;
1045+
}
10591046

10601047
epnew = exfat_get_dentry(sb, p_dir, newentry, &new_bh);
1061-
if (!epnew)
1062-
return -EIO;
1048+
if (!epnew) {
1049+
ret = -EIO;
1050+
goto put_old_es;
1051+
}
10631052

10641053
*epnew = *epold;
10651054
if (exfat_get_entry_type(epnew) == TYPE_FILE) {
10661055
epnew->dentry.file.attr |= cpu_to_le16(EXFAT_ATTR_ARCHIVE);
10671056
ei->attr |= EXFAT_ATTR_ARCHIVE;
10681057
}
10691058
exfat_update_bh(new_bh, sync);
1070-
brelse(old_bh);
10711059
brelse(new_bh);
10721060

1073-
epold = exfat_get_dentry(sb, p_dir, oldentry + 1, &old_bh);
1074-
if (!epold)
1075-
return -EIO;
1061+
epold = exfat_get_dentry_cached(&old_es, ES_IDX_STREAM);
10761062
epnew = exfat_get_dentry(sb, p_dir, newentry + 1, &new_bh);
10771063
if (!epnew) {
1078-
brelse(old_bh);
1079-
return -EIO;
1064+
ret = -EIO;
1065+
goto put_old_es;
10801066
}
10811067

10821068
*epnew = *epold;
10831069
exfat_update_bh(new_bh, sync);
1084-
brelse(old_bh);
10851070
brelse(new_bh);
10861071

10871072
ret = exfat_init_ext_entry(inode, p_dir, newentry,
10881073
num_new_entries, p_uniname);
10891074
if (ret)
1090-
return ret;
1075+
goto put_old_es;
10911076

1092-
exfat_remove_entries(inode, p_dir, oldentry, 0,
1093-
num_old_entries);
1077+
exfat_remove_entries(inode, &old_es, ES_IDX_FILE);
10941078
ei->dir = *p_dir;
10951079
ei->entry = newentry;
10961080
} else {
10971081
if (exfat_get_entry_type(epold) == TYPE_FILE) {
10981082
epold->dentry.file.attr |= cpu_to_le16(EXFAT_ATTR_ARCHIVE);
10991083
ei->attr |= EXFAT_ATTR_ARCHIVE;
11001084
}
1101-
exfat_update_bh(old_bh, sync);
1102-
brelse(old_bh);
11031085
ret = exfat_init_ext_entry(inode, p_dir, oldentry,
11041086
num_new_entries, p_uniname);
11051087
if (ret)
1106-
return ret;
1088+
goto put_old_es;
11071089

1108-
exfat_remove_entries(inode, p_dir, oldentry, num_new_entries,
1109-
num_old_entries);
1090+
exfat_remove_entries(inode, &old_es, num_new_entries);
11101091
}
1111-
return 0;
1092+
return exfat_put_dentry_set(&old_es, sync);
1093+
1094+
put_old_es:
1095+
exfat_put_dentry_set(&old_es, false);
1096+
return ret;
11121097
}
11131098

11141099
static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
11151100
int oldentry, struct exfat_chain *p_newdir,
11161101
struct exfat_uni_name *p_uniname, struct exfat_inode_info *ei)
11171102
{
1118-
int ret, newentry, num_new_entries, num_old_entries;
1103+
int ret, newentry, num_new_entries;
11191104
struct exfat_dentry *epmov, *epnew;
11201105
struct super_block *sb = inode->i_sb;
1121-
struct buffer_head *mov_bh, *new_bh;
1122-
1123-
epmov = exfat_get_dentry(sb, p_olddir, oldentry, &mov_bh);
1124-
if (!epmov)
1125-
return -EIO;
1126-
1127-
num_old_entries = exfat_count_ext_entries(sb, p_olddir, oldentry,
1128-
epmov);
1129-
if (num_old_entries < 0)
1130-
return -EIO;
1131-
num_old_entries++;
1106+
struct buffer_head *new_bh;
1107+
struct exfat_entry_set_cache mov_es;
11321108

11331109
num_new_entries = exfat_calc_num_entries(p_uniname);
11341110
if (num_new_entries < 0)
@@ -1138,45 +1114,54 @@ static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
11381114
if (newentry < 0)
11391115
return newentry; /* -EIO or -ENOSPC */
11401116

1141-
epnew = exfat_get_dentry(sb, p_newdir, newentry, &new_bh);
1142-
if (!epnew)
1117+
ret = exfat_get_dentry_set(&mov_es, sb, p_olddir, oldentry,
1118+
ES_ALL_ENTRIES);
1119+
if (ret)
11431120
return -EIO;
11441121

1122+
epmov = exfat_get_dentry_cached(&mov_es, ES_IDX_FILE);
1123+
epnew = exfat_get_dentry(sb, p_newdir, newentry, &new_bh);
1124+
if (!epnew) {
1125+
ret = -EIO;
1126+
goto put_mov_es;
1127+
}
1128+
11451129
*epnew = *epmov;
11461130
if (exfat_get_entry_type(epnew) == TYPE_FILE) {
11471131
epnew->dentry.file.attr |= cpu_to_le16(EXFAT_ATTR_ARCHIVE);
11481132
ei->attr |= EXFAT_ATTR_ARCHIVE;
11491133
}
11501134
exfat_update_bh(new_bh, IS_DIRSYNC(inode));
1151-
brelse(mov_bh);
11521135
brelse(new_bh);
11531136

1154-
epmov = exfat_get_dentry(sb, p_olddir, oldentry + 1, &mov_bh);
1155-
if (!epmov)
1156-
return -EIO;
1137+
epmov = exfat_get_dentry_cached(&mov_es, ES_IDX_STREAM);
11571138
epnew = exfat_get_dentry(sb, p_newdir, newentry + 1, &new_bh);
11581139
if (!epnew) {
1159-
brelse(mov_bh);
1160-
return -EIO;
1140+
ret = -EIO;
1141+
goto put_mov_es;
11611142
}
11621143

11631144
*epnew = *epmov;
11641145
exfat_update_bh(new_bh, IS_DIRSYNC(inode));
1165-
brelse(mov_bh);
11661146
brelse(new_bh);
11671147

11681148
ret = exfat_init_ext_entry(inode, p_newdir, newentry, num_new_entries,
11691149
p_uniname);
11701150
if (ret)
11711151
return ret;
11721152

1173-
exfat_remove_entries(inode, p_olddir, oldentry, 0, num_old_entries);
1153+
exfat_remove_entries(inode, &mov_es, ES_IDX_FILE);
11741154

11751155
exfat_chain_set(&ei->dir, p_newdir->dir, p_newdir->size,
11761156
p_newdir->flags);
11771157

11781158
ei->entry = newentry;
1179-
return 0;
1159+
return exfat_put_dentry_set(&mov_es, IS_DIRSYNC(inode));
1160+
1161+
put_mov_es:
1162+
exfat_put_dentry_set(&mov_es, false);
1163+
1164+
return ret;
11801165
}
11811166

11821167
/* rename or move a old file into a new file */
@@ -1194,7 +1179,6 @@ static int __exfat_rename(struct inode *old_parent_inode,
11941179
struct exfat_sb_info *sbi = EXFAT_SB(sb);
11951180
const unsigned char *new_path = new_dentry->d_name.name;
11961181
struct inode *new_inode = new_dentry->d_inode;
1197-
int num_entries;
11981182
struct exfat_inode_info *new_ei = NULL;
11991183
unsigned int new_entry_type = TYPE_UNUSED;
12001184
int new_entry = 0;
@@ -1265,25 +1249,21 @@ static int __exfat_rename(struct inode *old_parent_inode,
12651249
&newdir, &uni_name, ei);
12661250

12671251
if (!ret && new_inode) {
1252+
struct exfat_entry_set_cache es;
1253+
12681254
/* delete entries of new_dir */
1269-
ep = exfat_get_dentry(sb, p_dir, new_entry, &new_bh);
1270-
if (!ep) {
1255+
ret = exfat_get_dentry_set(&es, sb, p_dir, new_entry,
1256+
ES_ALL_ENTRIES);
1257+
if (ret) {
12711258
ret = -EIO;
12721259
goto del_out;
12731260
}
12741261

1275-
num_entries = exfat_count_ext_entries(sb, p_dir, new_entry, ep);
1276-
if (num_entries < 0) {
1277-
ret = -EIO;
1278-
goto del_out;
1279-
}
1280-
brelse(new_bh);
1262+
exfat_remove_entries(new_inode, &es, ES_IDX_FILE);
12811263

1282-
if (exfat_remove_entries(new_inode, p_dir, new_entry, 0,
1283-
num_entries + 1)) {
1284-
ret = -EIO;
1264+
ret = exfat_put_dentry_set(&es, IS_DIRSYNC(new_inode));
1265+
if (ret)
12851266
goto del_out;
1286-
}
12871267

12881268
/* Free the clusters if new_inode is a dir(as if exfat_rmdir) */
12891269
if (new_entry_type == TYPE_DIR &&

0 commit comments

Comments
 (0)