Skip to content

Commit 84e57d2

Browse files
committed
Merge tag 'exfat-for-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat
Pull exfat update from Namjae Jeon: - simplify and remove some redundant directory entry code - optimize the size of exfat_entry_set_cache and its allocation policy - improve the performance for creating files and directories * tag 'exfat-for-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat: exfat: reuse exfat_find_location() to simplify exfat_get_dentry_set() exfat: fix overflow in sector and cluster conversion exfat: remove i_size_write() from __exfat_truncate() exfat: remove argument 'size' from exfat_truncate() exfat: remove unnecessary arguments from exfat_find_dir_entry() exfat: remove unneeded codes from __exfat_rename() exfat: remove call ilog2() from exfat_readdir() exfat: replace magic numbers with Macros exfat: rename exfat_free_dentry_set() to exfat_put_dentry_set() exfat: move exfat_entry_set_cache from heap to stack exfat: support dynamic allocate bh for exfat_entry_set_cache exfat: reduce the size of exfat_entry_set_cache exfat: hint the empty entry which at the end of cluster chain exfat: simplify empty entry hint
2 parents 23dc9c7 + 36955d3 commit 84e57d2

File tree

5 files changed

+187
-145
lines changed

5 files changed

+187
-145
lines changed

fs/exfat/dir.c

Lines changed: 104 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,9 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
3333
struct exfat_chain *p_dir, int entry, unsigned short *uniname)
3434
{
3535
int i;
36-
struct exfat_entry_set_cache *es;
36+
struct exfat_entry_set_cache es;
3737

38-
es = exfat_get_dentry_set(sb, p_dir, entry, ES_ALL_ENTRIES);
39-
if (!es)
38+
if (exfat_get_dentry_set(&es, sb, p_dir, entry, ES_ALL_ENTRIES))
4039
return;
4140

4241
/*
@@ -45,8 +44,8 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
4544
* Third entry : first file-name entry
4645
* So, the index of first file-name dentry should start from 2.
4746
*/
48-
for (i = 2; i < es->num_entries; i++) {
49-
struct exfat_dentry *ep = exfat_get_dentry_cached(es, i);
47+
for (i = ES_IDX_FIRST_FILENAME; i < es.num_entries; i++) {
48+
struct exfat_dentry *ep = exfat_get_dentry_cached(&es, i);
5049

5150
/* end of name entry */
5251
if (exfat_get_entry_type(ep) != TYPE_EXTEND)
@@ -56,13 +55,13 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
5655
uniname += EXFAT_FILE_NAME_LEN;
5756
}
5857

59-
exfat_free_dentry_set(es, false);
58+
exfat_put_dentry_set(&es, false);
6059
}
6160

6261
/* read a directory entry from the opened directory */
6362
static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_entry *dir_entry)
6463
{
65-
int i, dentries_per_clu, dentries_per_clu_bits = 0, num_ext;
64+
int i, dentries_per_clu, num_ext;
6665
unsigned int type, clu_offset, max_dentries;
6766
struct exfat_chain dir, clu;
6867
struct exfat_uni_name uni_name;
@@ -84,11 +83,10 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
8483
EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags);
8584

8685
dentries_per_clu = sbi->dentries_per_clu;
87-
dentries_per_clu_bits = ilog2(dentries_per_clu);
8886
max_dentries = (unsigned int)min_t(u64, MAX_EXFAT_DENTRIES,
89-
(u64)sbi->num_clusters << dentries_per_clu_bits);
87+
(u64)EXFAT_CLU_TO_DEN(sbi->num_clusters, sbi));
9088

91-
clu_offset = dentry >> dentries_per_clu_bits;
89+
clu_offset = EXFAT_DEN_TO_CLU(dentry, sbi);
9290
exfat_chain_dup(&clu, &dir);
9391

9492
if (clu.flags == ALLOC_NO_FAT_CHAIN) {
@@ -163,7 +161,7 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
163161
dir_entry->entry = dentry;
164162
brelse(bh);
165163

166-
ei->hint_bmap.off = dentry >> dentries_per_clu_bits;
164+
ei->hint_bmap.off = EXFAT_DEN_TO_CLU(dentry, sbi);
167165
ei->hint_bmap.clu = clu.dir;
168166

169167
*cpos = EXFAT_DEN_TO_B(dentry + 1 + num_ext);
@@ -337,7 +335,7 @@ int exfat_calc_num_entries(struct exfat_uni_name *p_uniname)
337335
return -EINVAL;
338336

339337
/* 1 file entry + 1 stream entry + name entries */
340-
return ((len - 1) / EXFAT_FILE_NAME_LEN + 3);
338+
return ES_ENTRY_NUM(len);
341339
}
342340

343341
unsigned int exfat_get_entry_type(struct exfat_dentry *ep)
@@ -592,18 +590,18 @@ void exfat_update_dir_chksum_with_entry_set(struct exfat_entry_set_cache *es)
592590
unsigned short chksum = 0;
593591
struct exfat_dentry *ep;
594592

595-
for (i = 0; i < es->num_entries; i++) {
593+
for (i = ES_IDX_FILE; i < es->num_entries; i++) {
596594
ep = exfat_get_dentry_cached(es, i);
597595
chksum = exfat_calc_chksum16(ep, DENTRY_SIZE, chksum,
598596
chksum_type);
599597
chksum_type = CS_DEFAULT;
600598
}
601-
ep = exfat_get_dentry_cached(es, 0);
599+
ep = exfat_get_dentry_cached(es, ES_IDX_FILE);
602600
ep->dentry.file.checksum = cpu_to_le16(chksum);
603601
es->modified = true;
604602
}
605603

606-
int exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync)
604+
int exfat_put_dentry_set(struct exfat_entry_set_cache *es, int sync)
607605
{
608606
int i, err = 0;
609607

@@ -615,7 +613,10 @@ int exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync)
615613
bforget(es->bh[i]);
616614
else
617615
brelse(es->bh[i]);
618-
kfree(es);
616+
617+
if (IS_DYNAMIC_ES(es))
618+
kfree(es->bh);
619+
619620
return err;
620621
}
621622

@@ -812,89 +813,118 @@ struct exfat_dentry *exfat_get_dentry_cached(
812813
* pointer of entry set on success,
813814
* NULL on failure.
814815
*/
815-
struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
816-
struct exfat_chain *p_dir, int entry, unsigned int type)
816+
int exfat_get_dentry_set(struct exfat_entry_set_cache *es,
817+
struct super_block *sb, struct exfat_chain *p_dir, int entry,
818+
unsigned int type)
817819
{
818820
int ret, i, num_bh;
819-
unsigned int off, byte_offset, clu = 0;
821+
unsigned int off;
820822
sector_t sec;
821823
struct exfat_sb_info *sbi = EXFAT_SB(sb);
822-
struct exfat_entry_set_cache *es;
823824
struct exfat_dentry *ep;
824825
int num_entries;
825826
enum exfat_validate_dentry_mode mode = ES_MODE_STARTED;
826827
struct buffer_head *bh;
827828

828829
if (p_dir->dir == DIR_DELETED) {
829830
exfat_err(sb, "access to deleted dentry");
830-
return NULL;
831+
return -EIO;
831832
}
832833

833-
byte_offset = EXFAT_DEN_TO_B(entry);
834-
ret = exfat_walk_fat_chain(sb, p_dir, byte_offset, &clu);
834+
ret = exfat_find_location(sb, p_dir, entry, &sec, &off);
835835
if (ret)
836-
return NULL;
836+
return ret;
837837

838-
es = kzalloc(sizeof(*es), GFP_KERNEL);
839-
if (!es)
840-
return NULL;
838+
memset(es, 0, sizeof(*es));
841839
es->sb = sb;
842840
es->modified = false;
843-
844-
/* byte offset in cluster */
845-
byte_offset = EXFAT_CLU_OFFSET(byte_offset, sbi);
846-
847-
/* byte offset in sector */
848-
off = EXFAT_BLK_OFFSET(byte_offset, sb);
849841
es->start_off = off;
850-
851-
/* sector offset in cluster */
852-
sec = EXFAT_B_TO_BLK(byte_offset, sb);
853-
sec += exfat_cluster_to_sector(sbi, clu);
842+
es->bh = es->__bh;
854843

855844
bh = sb_bread(sb, sec);
856845
if (!bh)
857-
goto free_es;
846+
return -EIO;
858847
es->bh[es->num_bh++] = bh;
859848

860-
ep = exfat_get_dentry_cached(es, 0);
849+
ep = exfat_get_dentry_cached(es, ES_IDX_FILE);
861850
if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode))
862-
goto free_es;
851+
goto put_es;
863852

864853
num_entries = type == ES_ALL_ENTRIES ?
865854
ep->dentry.file.num_ext + 1 : type;
866855
es->num_entries = num_entries;
867856

868857
num_bh = EXFAT_B_TO_BLK_ROUND_UP(off + num_entries * DENTRY_SIZE, sb);
858+
if (num_bh > ARRAY_SIZE(es->__bh)) {
859+
es->bh = kmalloc_array(num_bh, sizeof(*es->bh), GFP_KERNEL);
860+
if (!es->bh) {
861+
brelse(bh);
862+
return -ENOMEM;
863+
}
864+
es->bh[0] = bh;
865+
}
866+
869867
for (i = 1; i < num_bh; i++) {
870868
/* get the next sector */
871869
if (exfat_is_last_sector_in_cluster(sbi, sec)) {
870+
unsigned int clu = exfat_sector_to_cluster(sbi, sec);
871+
872872
if (p_dir->flags == ALLOC_NO_FAT_CHAIN)
873873
clu++;
874874
else if (exfat_get_next_cluster(sb, &clu))
875-
goto free_es;
875+
goto put_es;
876876
sec = exfat_cluster_to_sector(sbi, clu);
877877
} else {
878878
sec++;
879879
}
880880

881881
bh = sb_bread(sb, sec);
882882
if (!bh)
883-
goto free_es;
883+
goto put_es;
884884
es->bh[es->num_bh++] = bh;
885885
}
886886

887887
/* validate cached dentries */
888-
for (i = 1; i < num_entries; i++) {
888+
for (i = ES_IDX_STREAM; i < num_entries; i++) {
889889
ep = exfat_get_dentry_cached(es, i);
890890
if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode))
891-
goto free_es;
891+
goto put_es;
892892
}
893-
return es;
893+
return 0;
894+
895+
put_es:
896+
exfat_put_dentry_set(es, false);
897+
return -EIO;
898+
}
894899

895-
free_es:
896-
exfat_free_dentry_set(es, false);
897-
return NULL;
900+
static inline void exfat_reset_empty_hint(struct exfat_hint_femp *hint_femp)
901+
{
902+
hint_femp->eidx = EXFAT_HINT_NONE;
903+
hint_femp->count = 0;
904+
}
905+
906+
static inline void exfat_set_empty_hint(struct exfat_inode_info *ei,
907+
struct exfat_hint_femp *candi_empty, struct exfat_chain *clu,
908+
int dentry, int num_entries, int entry_type)
909+
{
910+
if (ei->hint_femp.eidx == EXFAT_HINT_NONE ||
911+
ei->hint_femp.eidx > dentry) {
912+
int total_entries = EXFAT_B_TO_DEN(i_size_read(&ei->vfs_inode));
913+
914+
if (candi_empty->count == 0) {
915+
candi_empty->cur = *clu;
916+
candi_empty->eidx = dentry;
917+
}
918+
919+
if (entry_type == TYPE_UNUSED)
920+
candi_empty->count += total_entries - dentry;
921+
else
922+
candi_empty->count++;
923+
924+
if (candi_empty->count == num_entries ||
925+
candi_empty->count + candi_empty->eidx == total_entries)
926+
ei->hint_femp = *candi_empty;
927+
}
898928
}
899929

900930
enum {
@@ -917,17 +947,21 @@ enum {
917947
*/
918948
int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
919949
struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname,
920-
int num_entries, unsigned int type, struct exfat_hint *hint_opt)
950+
struct exfat_hint *hint_opt)
921951
{
922952
int i, rewind = 0, dentry = 0, end_eidx = 0, num_ext = 0, len;
923953
int order, step, name_len = 0;
924-
int dentries_per_clu, num_empty = 0;
954+
int dentries_per_clu;
925955
unsigned int entry_type;
926956
unsigned short *uniname = NULL;
927957
struct exfat_chain clu;
928958
struct exfat_hint *hint_stat = &ei->hint_stat;
929959
struct exfat_hint_femp candi_empty;
930960
struct exfat_sb_info *sbi = EXFAT_SB(sb);
961+
int num_entries = exfat_calc_num_entries(p_uniname);
962+
963+
if (num_entries < 0)
964+
return num_entries;
931965

932966
dentries_per_clu = sbi->dentries_per_clu;
933967

@@ -939,10 +973,13 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
939973
end_eidx = dentry;
940974
}
941975

942-
candi_empty.eidx = EXFAT_HINT_NONE;
976+
exfat_reset_empty_hint(&ei->hint_femp);
977+
943978
rewind:
944979
order = 0;
945980
step = DIRENT_STEP_FILE;
981+
exfat_reset_empty_hint(&candi_empty);
982+
946983
while (clu.dir != EXFAT_EOF_CLUSTER) {
947984
i = dentry & (dentries_per_clu - 1);
948985
for (; i < dentries_per_clu; i++, dentry++) {
@@ -962,44 +999,24 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
962999
entry_type == TYPE_DELETED) {
9631000
step = DIRENT_STEP_FILE;
9641001

965-
num_empty++;
966-
if (candi_empty.eidx == EXFAT_HINT_NONE &&
967-
num_empty == 1) {
968-
exfat_chain_set(&candi_empty.cur,
969-
clu.dir, clu.size, clu.flags);
970-
}
971-
972-
if (candi_empty.eidx == EXFAT_HINT_NONE &&
973-
num_empty >= num_entries) {
974-
candi_empty.eidx =
975-
dentry - (num_empty - 1);
976-
WARN_ON(candi_empty.eidx < 0);
977-
candi_empty.count = num_empty;
978-
979-
if (ei->hint_femp.eidx ==
980-
EXFAT_HINT_NONE ||
981-
candi_empty.eidx <=
982-
ei->hint_femp.eidx)
983-
ei->hint_femp = candi_empty;
984-
}
1002+
exfat_set_empty_hint(ei, &candi_empty, &clu,
1003+
dentry, num_entries,
1004+
entry_type);
9851005

9861006
brelse(bh);
9871007
if (entry_type == TYPE_UNUSED)
9881008
goto not_found;
9891009
continue;
9901010
}
9911011

992-
num_empty = 0;
993-
candi_empty.eidx = EXFAT_HINT_NONE;
1012+
exfat_reset_empty_hint(&candi_empty);
9941013

9951014
if (entry_type == TYPE_FILE || entry_type == TYPE_DIR) {
9961015
step = DIRENT_STEP_FILE;
9971016
hint_opt->clu = clu.dir;
9981017
hint_opt->eidx = i;
999-
if (type == TYPE_ALL || type == entry_type) {
1000-
num_ext = ep->dentry.file.num_ext;
1001-
step = DIRENT_STEP_STRM;
1002-
}
1018+
num_ext = ep->dentry.file.num_ext;
1019+
step = DIRENT_STEP_STRM;
10031020
brelse(bh);
10041021
continue;
10051022
}
@@ -1090,12 +1107,19 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
10901107
rewind = 1;
10911108
dentry = 0;
10921109
clu.dir = p_dir->dir;
1093-
/* reset empty hint */
1094-
num_empty = 0;
1095-
candi_empty.eidx = EXFAT_HINT_NONE;
10961110
goto rewind;
10971111
}
10981112

1113+
/*
1114+
* set the EXFAT_EOF_CLUSTER flag to avoid search
1115+
* from the beginning again when allocated a new cluster
1116+
*/
1117+
if (ei->hint_femp.eidx == EXFAT_HINT_NONE) {
1118+
ei->hint_femp.cur.dir = EXFAT_EOF_CLUSTER;
1119+
ei->hint_femp.eidx = p_dir->size * dentries_per_clu;
1120+
ei->hint_femp.count = 0;
1121+
}
1122+
10991123
/* initialized hint_stat */
11001124
hint_stat->clu = p_dir->dir;
11011125
hint_stat->eidx = 0;

0 commit comments

Comments
 (0)