Skip to content

Commit a62fe21

Browse files
committed
Merge tag 'exfat-for-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat
Pull exfat updates from Namjae Jeon: - Implement FALLOC_FL_ALLOCATE_RANGE to add support for preallocating clusters without zeroing, helping to reduce file fragmentation - Add a unified block readahead helper for FAT chain conversion, bitmap allocation, and directory entry lookups - Optimize exfat_chain_cont_cluster() by caching buffer heads to minimize mark_buffer_dirty() and mirroring overhead during NO_FAT_CHAIN to FAT_CHAIN conversion - Switch to truncate_inode_pages_final() in evict_inode() to prevent BUG_ON caused by shadow entries during reclaim - Fix a 32-bit truncation bug in directory entry calculations by ensuring proper bitwise coercion - Fix sb->s_maxbytes calculation to correctly reflect the maximum possible volume size for a given cluster size, resolving xfstests generic/213 - Introduced exfat_cluster_walk() helper to traverse FAT chains by a specified step, handling both ALLOC_NO_FAT_CHAIN and ALLOC_FAT_CHAIN modes - Introduced exfat_chain_advance() helper to advance an exfat_chain structure, updating both the current cluster and remaining size - Remove dead assignments and fix Smatch warnings * tag 'exfat-for-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat: exfat: use exfat_chain_advance helper exfat: introduce exfat_chain_advance helper exfat: remove NULL cache pointer case in exfat_ent_get exfat: use exfat_cluster_walk helper exfat: introduce exfat_cluster_walk helper exfat: fix incorrect directory checksum after rename to shorter name exfat: fix s_maxbytes exfat: fix passing zero to ERR_PTR() in exfat_mkdir() exfat: fix error handling for FAT table operations exfat: optimize exfat_chain_cont_cluster with cached buffer heads exfat: drop redundant sec parameter from exfat_mirror_bh exfat: use readahead helper in exfat_get_dentry exfat: use readahead helper in exfat_allocate_bitmap exfat: add block readahead in exfat_chain_cont_cluster exfat: add fallocate FALLOC_FL_ALLOCATE_RANGE support exfat: Fix bitwise operation having different size exfat: Drop dead assignment of num_clusters exfat: use truncate_inode_pages_final() at evict_inode()
2 parents f272982 + 08cf4a8 commit a62fe21

10 files changed

Lines changed: 265 additions & 218 deletions

File tree

fs/exfat/balloc.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,10 @@ static int exfat_allocate_bitmap(struct super_block *sb,
7474
struct exfat_dentry *ep)
7575
{
7676
struct exfat_sb_info *sbi = EXFAT_SB(sb);
77-
struct blk_plug plug;
7877
long long map_size;
7978
unsigned int i, j, need_map_size;
80-
sector_t sector;
81-
unsigned int max_ra_count;
79+
sector_t sector, end, ra;
80+
blkcnt_t ra_cnt = 0;
8281

8382
sbi->map_clu = le32_to_cpu(ep->dentry.bitmap.start_clu);
8483
map_size = le64_to_cpu(ep->dentry.bitmap.size);
@@ -100,17 +99,12 @@ static int exfat_allocate_bitmap(struct super_block *sb,
10099
if (!sbi->vol_amap)
101100
return -ENOMEM;
102101

103-
sector = exfat_cluster_to_sector(sbi, sbi->map_clu);
104-
max_ra_count = min(sb->s_bdi->ra_pages, sb->s_bdi->io_pages) <<
105-
(PAGE_SHIFT - sb->s_blocksize_bits);
102+
sector = ra = exfat_cluster_to_sector(sbi, sbi->map_clu);
103+
end = sector + sbi->map_sectors - 1;
104+
106105
for (i = 0; i < sbi->map_sectors; i++) {
107106
/* Trigger the next readahead in advance. */
108-
if (max_ra_count && 0 == (i % max_ra_count)) {
109-
blk_start_plug(&plug);
110-
for (j = i; j < min(max_ra_count, sbi->map_sectors - i) + i; j++)
111-
sb_breadahead(sb, sector + j);
112-
blk_finish_plug(&plug);
113-
}
107+
exfat_blk_readahead(sb, sector + i, &ra, &ra_cnt, end);
114108

115109
sbi->vol_amap[i] = sb_bread(sb, sector + i);
116110
if (!sbi->vol_amap[i])

fs/exfat/dir.c

Lines changed: 45 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -93,25 +93,19 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
9393
clu_offset = EXFAT_DEN_TO_CLU(dentry, sbi);
9494
exfat_chain_dup(&clu, &dir);
9595

96-
if (clu.flags == ALLOC_NO_FAT_CHAIN) {
97-
clu.dir += clu_offset;
98-
clu.size -= clu_offset;
99-
} else {
96+
if (clu.flags == ALLOC_FAT_CHAIN) {
10097
/* hint_information */
10198
if (clu_offset > 0 && ei->hint_bmap.off != EXFAT_EOF_CLUSTER &&
10299
ei->hint_bmap.off > 0 && clu_offset >= ei->hint_bmap.off) {
103100
clu_offset -= ei->hint_bmap.off;
104101
clu.dir = ei->hint_bmap.clu;
105-
}
106-
107-
while (clu_offset > 0 && clu.dir != EXFAT_EOF_CLUSTER) {
108-
if (exfat_get_next_cluster(sb, &(clu.dir)))
109-
return -EIO;
110-
111-
clu_offset--;
102+
clu.size -= ei->hint_bmap.off;
112103
}
113104
}
114105

106+
if (exfat_chain_advance(sb, &clu, clu_offset))
107+
return -EIO;
108+
115109
while (clu.dir != EXFAT_EOF_CLUSTER && dentry < max_dentries) {
116110
i = dentry & (dentries_per_clu - 1);
117111

@@ -160,15 +154,8 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
160154
return 0;
161155
}
162156

163-
if (clu.flags == ALLOC_NO_FAT_CHAIN) {
164-
if (--clu.size > 0)
165-
clu.dir++;
166-
else
167-
clu.dir = EXFAT_EOF_CLUSTER;
168-
} else {
169-
if (exfat_get_next_cluster(sb, &(clu.dir)))
170-
return -EIO;
171-
}
157+
if (exfat_chain_advance(sb, &clu, 1))
158+
return -EIO;
172159
}
173160

174161
out:
@@ -249,7 +236,7 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx)
249236
*/
250237
if (err == -EIO) {
251238
cpos += 1 << (sb->s_blocksize_bits);
252-
cpos &= ~(sb->s_blocksize - 1);
239+
cpos &= ~(loff_t)(sb->s_blocksize - 1);
253240
}
254241

255242
err = -EIO;
@@ -490,6 +477,7 @@ void exfat_init_ext_entry(struct exfat_entry_set_cache *es, int num_entries,
490477
unsigned short *uniname = p_uniname->name;
491478
struct exfat_dentry *ep;
492479

480+
es->num_entries = num_entries;
493481
ep = exfat_get_dentry_cached(es, ES_IDX_FILE);
494482
ep->dentry.file.num_ext = (unsigned char)(num_entries - 1);
495483

@@ -561,38 +549,6 @@ int exfat_put_dentry_set(struct exfat_entry_set_cache *es, int sync)
561549
return err;
562550
}
563551

564-
static int exfat_walk_fat_chain(struct super_block *sb,
565-
struct exfat_chain *p_dir, unsigned int byte_offset,
566-
unsigned int *clu)
567-
{
568-
struct exfat_sb_info *sbi = EXFAT_SB(sb);
569-
unsigned int clu_offset;
570-
unsigned int cur_clu;
571-
572-
clu_offset = EXFAT_B_TO_CLU(byte_offset, sbi);
573-
cur_clu = p_dir->dir;
574-
575-
if (p_dir->flags == ALLOC_NO_FAT_CHAIN) {
576-
cur_clu += clu_offset;
577-
} else {
578-
while (clu_offset > 0) {
579-
if (exfat_get_next_cluster(sb, &cur_clu))
580-
return -EIO;
581-
if (cur_clu == EXFAT_EOF_CLUSTER) {
582-
exfat_fs_error(sb,
583-
"invalid dentry access beyond EOF (clu : %u, eidx : %d)",
584-
p_dir->dir,
585-
EXFAT_B_TO_DEN(byte_offset));
586-
return -EIO;
587-
}
588-
clu_offset--;
589-
}
590-
}
591-
592-
*clu = cur_clu;
593-
return 0;
594-
}
595-
596552
static int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir,
597553
int entry, sector_t *sector, int *offset)
598554
{
@@ -602,10 +558,19 @@ static int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir
602558

603559
off = EXFAT_DEN_TO_B(entry);
604560

605-
ret = exfat_walk_fat_chain(sb, p_dir, off, &clu);
561+
clu = p_dir->dir;
562+
ret = exfat_cluster_walk(sb, &clu, EXFAT_B_TO_CLU(off, sbi), p_dir->flags);
606563
if (ret)
607564
return ret;
608565

566+
if (clu == EXFAT_EOF_CLUSTER) {
567+
exfat_fs_error(sb,
568+
"unexpected early break in cluster chain (clu : %u, len : %d)",
569+
p_dir->dir,
570+
EXFAT_B_TO_CLU(off, sbi));
571+
return -EIO;
572+
}
573+
609574
if (!exfat_test_bitmap(sb, clu)) {
610575
exfat_err(sb, "failed to test cluster bit(%u)", clu);
611576
return -EIO;
@@ -623,44 +588,11 @@ static int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir
623588
return 0;
624589
}
625590

626-
#define EXFAT_MAX_RA_SIZE (128*1024)
627-
static int exfat_dir_readahead(struct super_block *sb, sector_t sec)
628-
{
629-
struct exfat_sb_info *sbi = EXFAT_SB(sb);
630-
struct buffer_head *bh;
631-
unsigned int max_ra_count = EXFAT_MAX_RA_SIZE >> sb->s_blocksize_bits;
632-
unsigned int page_ra_count = PAGE_SIZE >> sb->s_blocksize_bits;
633-
unsigned int adj_ra_count = max(sbi->sect_per_clus, page_ra_count);
634-
unsigned int ra_count = min(adj_ra_count, max_ra_count);
635-
636-
/* Read-ahead is not required */
637-
if (sbi->sect_per_clus == 1)
638-
return 0;
639-
640-
if (sec < sbi->data_start_sector) {
641-
exfat_err(sb, "requested sector is invalid(sect:%llu, root:%llu)",
642-
(unsigned long long)sec, sbi->data_start_sector);
643-
return -EIO;
644-
}
645-
646-
/* Not sector aligned with ra_count, resize ra_count to page size */
647-
if ((sec - sbi->data_start_sector) & (ra_count - 1))
648-
ra_count = page_ra_count;
649-
650-
bh = sb_find_get_block(sb, sec);
651-
if (!bh || !buffer_uptodate(bh)) {
652-
unsigned int i;
653-
654-
for (i = 0; i < ra_count; i++)
655-
sb_breadahead(sb, (sector_t)(sec + i));
656-
}
657-
brelse(bh);
658-
return 0;
659-
}
660-
661591
struct exfat_dentry *exfat_get_dentry(struct super_block *sb,
662592
struct exfat_chain *p_dir, int entry, struct buffer_head **bh)
663593
{
594+
struct exfat_sb_info *sbi = EXFAT_SB(sb);
595+
unsigned int sect_per_clus = sbi->sect_per_clus;
664596
unsigned int dentries_per_page = EXFAT_B_TO_DEN(PAGE_SIZE);
665597
int off;
666598
sector_t sec;
@@ -673,9 +605,18 @@ struct exfat_dentry *exfat_get_dentry(struct super_block *sb,
673605
if (exfat_find_location(sb, p_dir, entry, &sec, &off))
674606
return NULL;
675607

676-
if (p_dir->dir != EXFAT_FREE_CLUSTER &&
677-
!(entry & (dentries_per_page - 1)))
678-
exfat_dir_readahead(sb, sec);
608+
if (sect_per_clus > 1 &&
609+
(entry & (dentries_per_page - 1)) == 0) {
610+
sector_t ra = sec;
611+
blkcnt_t cnt = 0;
612+
unsigned int ra_count = sect_per_clus;
613+
614+
/* Not sector aligned with ra_count, resize ra_count to page size */
615+
if ((sec - sbi->data_start_sector) & (ra_count - 1))
616+
ra_count = PAGE_SIZE >> sb->s_blocksize_bits;
617+
618+
exfat_blk_readahead(sb, sec, &ra, &cnt, sec + ra_count - 1);
619+
}
679620

680621
*bh = sb_bread(sb, sec);
681622
if (!*bh)
@@ -815,9 +756,7 @@ static int __exfat_get_dentry_set(struct exfat_entry_set_cache *es,
815756
if (exfat_is_last_sector_in_cluster(sbi, sec)) {
816757
unsigned int clu = exfat_sector_to_cluster(sbi, sec);
817758

818-
if (p_dir->flags == ALLOC_NO_FAT_CHAIN)
819-
clu++;
820-
else if (exfat_get_next_cluster(sb, &clu))
759+
if (exfat_cluster_walk(sb, &clu, 1, p_dir->flags))
821760
goto put_es;
822761
sec = exfat_cluster_to_sector(sbi, clu);
823762
} else {
@@ -1133,19 +1072,12 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
11331072
step = DIRENT_STEP_FILE;
11341073
}
11351074

1136-
if (clu.flags == ALLOC_NO_FAT_CHAIN) {
1137-
if (--clu.size > 0)
1138-
clu.dir++;
1139-
else
1140-
clu.dir = EXFAT_EOF_CLUSTER;
1141-
} else {
1142-
if (exfat_get_next_cluster(sb, &clu.dir))
1143-
return -EIO;
1075+
if (exfat_chain_advance(sb, &clu, 1))
1076+
return -EIO;
11441077

1145-
/* break if the cluster chain includes a loop */
1146-
if (unlikely(++clu_count > EXFAT_DATA_CLUSTER_COUNT(sbi)))
1147-
goto not_found;
1148-
}
1078+
/* break if the cluster chain includes a loop */
1079+
if (unlikely(++clu_count > EXFAT_DATA_CLUSTER_COUNT(sbi)))
1080+
goto not_found;
11491081
}
11501082

11511083
not_found:
@@ -1180,14 +1112,7 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
11801112
if (!((dentry + 1) & (dentries_per_clu - 1))) {
11811113
int ret = 0;
11821114

1183-
if (clu.flags == ALLOC_NO_FAT_CHAIN) {
1184-
if (--clu.size > 0)
1185-
clu.dir++;
1186-
else
1187-
clu.dir = EXFAT_EOF_CLUSTER;
1188-
} else {
1189-
ret = exfat_get_next_cluster(sb, &clu.dir);
1190-
}
1115+
ret = exfat_chain_advance(sb, &clu, 1);
11911116

11921117
if (ret || clu.dir == EXFAT_EOF_CLUSTER) {
11931118
/* just initialized hint_stat */
@@ -1232,20 +1157,12 @@ int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir)
12321157
count++;
12331158
}
12341159

1235-
if (clu.flags == ALLOC_NO_FAT_CHAIN) {
1236-
if (--clu.size > 0)
1237-
clu.dir++;
1238-
else
1239-
clu.dir = EXFAT_EOF_CLUSTER;
1240-
} else {
1241-
if (exfat_get_next_cluster(sb, &(clu.dir)))
1242-
return -EIO;
1243-
1244-
if (unlikely(++clu_count > sbi->used_clusters)) {
1245-
exfat_fs_error(sb, "FAT or bitmap is corrupted");
1246-
return -EIO;
1247-
}
1160+
if (exfat_chain_advance(sb, &clu, 1))
1161+
return -EIO;
12481162

1163+
if (unlikely(++clu_count > sbi->used_clusters)) {
1164+
exfat_fs_error(sb, "FAT or bitmap is corrupted");
1165+
return -EIO;
12491166
}
12501167
}
12511168

0 commit comments

Comments
 (0)