Skip to content

Commit 172f7c9

Browse files
committed
Merge tag 'exfat-for-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat
Pull exfat updates from Namjae Jeon: - Fix random stack corruption and incorrect error returns in exfat_get_block() - Optimize exfat_get_block() by improving checking corner cases - Fix an endless loop by self-linked chain in exfat_find_last_cluster - Remove dead EXFAT_CLUSTERS_UNTRACKED codes - Add missing shutdown check - Improve the delete performance with discard mount option * tag 'exfat-for-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat: exfat: call bh_read in get_block only when necessary exfat: fix potential wrong error return from get_block exfat: fix missing shutdown check exfat: fix the infinite loop in exfat_find_last_cluster() exfat: fix random stack corruption after get_block exfat: remove count used cluster from exfat_statfs() exfat: support batch discard of clusters when freeing clusters
2 parents f64a72b + c73e680 commit 172f7c9

File tree

6 files changed

+140
-88
lines changed

6 files changed

+140
-88
lines changed

fs/exfat/balloc.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
147147
unsigned int ent_idx;
148148
struct super_block *sb = inode->i_sb;
149149
struct exfat_sb_info *sbi = EXFAT_SB(sb);
150-
struct exfat_mount_options *opts = &sbi->options;
151150

152151
if (!is_valid_cluster(sbi, clu))
153152
return -EIO;
@@ -163,19 +162,6 @@ int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
163162

164163
exfat_update_bh(sbi->vol_amap[i], sync);
165164

166-
if (opts->discard) {
167-
int ret_discard;
168-
169-
ret_discard = sb_issue_discard(sb,
170-
exfat_cluster_to_sector(sbi, clu),
171-
(1 << sbi->sect_per_clus_bits), GFP_NOFS, 0);
172-
173-
if (ret_discard == -EOPNOTSUPP) {
174-
exfat_err(sb, "discard not supported by device, disabling");
175-
opts->discard = 0;
176-
}
177-
}
178-
179165
return 0;
180166
}
181167

fs/exfat/exfat_fs.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414

1515
#define EXFAT_ROOT_INO 1
1616

17-
#define EXFAT_CLUSTERS_UNTRACKED (~0u)
18-
1917
/*
2018
* exfat error flags
2119
*/

fs/exfat/fatent.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,20 @@ int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain,
144144
return 0;
145145
}
146146

147+
static inline void exfat_discard_cluster(struct super_block *sb,
148+
unsigned int clu, unsigned int num_clusters)
149+
{
150+
int ret;
151+
struct exfat_sb_info *sbi = EXFAT_SB(sb);
152+
153+
ret = sb_issue_discard(sb, exfat_cluster_to_sector(sbi, clu),
154+
sbi->sect_per_clus * num_clusters, GFP_NOFS, 0);
155+
if (ret == -EOPNOTSUPP) {
156+
exfat_err(sb, "discard not supported by device, disabling");
157+
sbi->options.discard = 0;
158+
}
159+
}
160+
147161
/* This function must be called with bitmap_lock held */
148162
static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
149163
{
@@ -196,7 +210,12 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain
196210
clu++;
197211
num_clusters++;
198212
} while (num_clusters < p_chain->size);
213+
214+
if (sbi->options.discard)
215+
exfat_discard_cluster(sb, p_chain->dir, p_chain->size);
199216
} else {
217+
unsigned int nr_clu = 1;
218+
200219
do {
201220
bool sync = false;
202221
unsigned int n_clu = clu;
@@ -215,6 +234,16 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain
215234

216235
if (exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))))
217236
break;
237+
238+
if (sbi->options.discard) {
239+
if (n_clu == clu + 1)
240+
nr_clu++;
241+
else {
242+
exfat_discard_cluster(sb, clu - nr_clu + 1, nr_clu);
243+
nr_clu = 1;
244+
}
245+
}
246+
218247
clu = n_clu;
219248
num_clusters++;
220249

@@ -265,7 +294,7 @@ int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain,
265294
clu = next;
266295
if (exfat_ent_get(sb, clu, &next))
267296
return -EIO;
268-
} while (next != EXFAT_EOF_CLUSTER);
297+
} while (next != EXFAT_EOF_CLUSTER && count <= p_chain->size);
269298

270299
if (p_chain->size != count) {
271300
exfat_fs_error(sb,

fs/exfat/file.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,9 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
582582
loff_t pos = iocb->ki_pos;
583583
loff_t valid_size;
584584

585+
if (unlikely(exfat_forced_shutdown(inode->i_sb)))
586+
return -EIO;
587+
585588
inode_lock(inode);
586589

587590
valid_size = ei->valid_size;
@@ -635,6 +638,16 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
635638
return ret;
636639
}
637640

641+
static ssize_t exfat_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
642+
{
643+
struct inode *inode = file_inode(iocb->ki_filp);
644+
645+
if (unlikely(exfat_forced_shutdown(inode->i_sb)))
646+
return -EIO;
647+
648+
return generic_file_read_iter(iocb, iter);
649+
}
650+
638651
static vm_fault_t exfat_page_mkwrite(struct vm_fault *vmf)
639652
{
640653
int err;
@@ -672,22 +685,34 @@ static const struct vm_operations_struct exfat_file_vm_ops = {
672685

673686
static int exfat_file_mmap(struct file *file, struct vm_area_struct *vma)
674687
{
688+
if (unlikely(exfat_forced_shutdown(file_inode(file)->i_sb)))
689+
return -EIO;
690+
675691
file_accessed(file);
676692
vma->vm_ops = &exfat_file_vm_ops;
677693
return 0;
678694
}
679695

696+
static ssize_t exfat_splice_read(struct file *in, loff_t *ppos,
697+
struct pipe_inode_info *pipe, size_t len, unsigned int flags)
698+
{
699+
if (unlikely(exfat_forced_shutdown(file_inode(in)->i_sb)))
700+
return -EIO;
701+
702+
return filemap_splice_read(in, ppos, pipe, len, flags);
703+
}
704+
680705
const struct file_operations exfat_file_operations = {
681706
.llseek = generic_file_llseek,
682-
.read_iter = generic_file_read_iter,
707+
.read_iter = exfat_file_read_iter,
683708
.write_iter = exfat_file_write_iter,
684709
.unlocked_ioctl = exfat_ioctl,
685710
#ifdef CONFIG_COMPAT
686711
.compat_ioctl = exfat_compat_ioctl,
687712
#endif
688713
.mmap = exfat_file_mmap,
689714
.fsync = exfat_file_fsync,
690-
.splice_read = filemap_splice_read,
715+
.splice_read = exfat_splice_read,
691716
.splice_write = iter_file_splice_write,
692717
};
693718

fs/exfat/inode.c

Lines changed: 83 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,11 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
274274
sector_t last_block;
275275
sector_t phys = 0;
276276
sector_t valid_blks;
277+
loff_t i_size;
277278

278279
mutex_lock(&sbi->s_lock);
279-
last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size_read(inode), sb);
280+
i_size = i_size_read(inode);
281+
last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size, sb);
280282
if (iblock >= last_block && !create)
281283
goto done;
282284

@@ -305,77 +307,99 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
305307
if (buffer_delay(bh_result))
306308
clear_buffer_delay(bh_result);
307309

308-
if (create) {
310+
/*
311+
* In most cases, we just need to set bh_result to mapped, unmapped
312+
* or new status as follows:
313+
* 1. i_size == valid_size
314+
* 2. write case (create == 1)
315+
* 3. direct_read (!bh_result->b_folio)
316+
* -> the unwritten part will be zeroed in exfat_direct_IO()
317+
*
318+
* Otherwise, in the case of buffered read, it is necessary to take
319+
* care the last nested block if valid_size is not equal to i_size.
320+
*/
321+
if (i_size == ei->valid_size || create || !bh_result->b_folio)
309322
valid_blks = EXFAT_B_TO_BLK_ROUND_UP(ei->valid_size, sb);
323+
else
324+
valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb);
310325

311-
if (iblock + max_blocks < valid_blks) {
312-
/* The range has been written, map it */
313-
goto done;
314-
} else if (iblock < valid_blks) {
315-
/*
316-
* The range has been partially written,
317-
* map the written part.
318-
*/
319-
max_blocks = valid_blks - iblock;
320-
goto done;
321-
}
326+
/* The range has been fully written, map it */
327+
if (iblock + max_blocks < valid_blks)
328+
goto done;
322329

323-
/* The area has not been written, map and mark as new. */
324-
set_buffer_new(bh_result);
330+
/* The range has been partially written, map the written part */
331+
if (iblock < valid_blks) {
332+
max_blocks = valid_blks - iblock;
333+
goto done;
334+
}
325335

336+
/* The area has not been written, map and mark as new for create case */
337+
if (create) {
338+
set_buffer_new(bh_result);
326339
ei->valid_size = EXFAT_BLK_TO_B(iblock + max_blocks, sb);
327340
mark_inode_dirty(inode);
328-
} else {
329-
valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb);
341+
goto done;
342+
}
330343

331-
if (iblock + max_blocks < valid_blks) {
332-
/* The range has been written, map it */
344+
/*
345+
* The area has just one block partially written.
346+
* In that case, we should read and fill the unwritten part of
347+
* a block with zero.
348+
*/
349+
if (bh_result->b_folio && iblock == valid_blks &&
350+
(ei->valid_size & (sb->s_blocksize - 1))) {
351+
loff_t size, pos;
352+
void *addr;
353+
354+
max_blocks = 1;
355+
356+
/*
357+
* No buffer_head is allocated.
358+
* (1) bmap: It's enough to set blocknr without I/O.
359+
* (2) read: The unwritten part should be filled with zero.
360+
* If a folio does not have any buffers,
361+
* let's returns -EAGAIN to fallback to
362+
* block_read_full_folio() for per-bh IO.
363+
*/
364+
if (!folio_buffers(bh_result->b_folio)) {
365+
err = -EAGAIN;
333366
goto done;
334-
} else if (iblock < valid_blks) {
335-
/*
336-
* The area has been partially written,
337-
* map the written part.
338-
*/
339-
max_blocks = valid_blks - iblock;
367+
}
368+
369+
pos = EXFAT_BLK_TO_B(iblock, sb);
370+
size = ei->valid_size - pos;
371+
addr = folio_address(bh_result->b_folio) +
372+
offset_in_folio(bh_result->b_folio, pos);
373+
374+
/* Check if bh->b_data points to proper addr in folio */
375+
if (bh_result->b_data != addr) {
376+
exfat_fs_error_ratelimit(sb,
377+
"b_data(%p) != folio_addr(%p)",
378+
bh_result->b_data, addr);
379+
err = -EINVAL;
340380
goto done;
341-
} else if (iblock == valid_blks &&
342-
(ei->valid_size & (sb->s_blocksize - 1))) {
343-
/*
344-
* The block has been partially written,
345-
* zero the unwritten part and map the block.
346-
*/
347-
loff_t size, off, pos;
348-
349-
max_blocks = 1;
350-
351-
/*
352-
* For direct read, the unwritten part will be zeroed in
353-
* exfat_direct_IO()
354-
*/
355-
if (!bh_result->b_folio)
356-
goto done;
357-
358-
pos = EXFAT_BLK_TO_B(iblock, sb);
359-
size = ei->valid_size - pos;
360-
off = pos & (PAGE_SIZE - 1);
361-
362-
folio_set_bh(bh_result, bh_result->b_folio, off);
363-
err = bh_read(bh_result, 0);
364-
if (err < 0)
365-
goto unlock_ret;
366-
367-
folio_zero_segment(bh_result->b_folio, off + size,
368-
off + sb->s_blocksize);
369-
} else {
370-
/*
371-
* The range has not been written, clear the mapped flag
372-
* to only zero the cache and do not read from disk.
373-
*/
374-
clear_buffer_mapped(bh_result);
375381
}
382+
383+
/* Read a block */
384+
err = bh_read(bh_result, 0);
385+
if (err < 0)
386+
goto done;
387+
388+
/* Zero unwritten part of a block */
389+
memset(bh_result->b_data + size, 0, bh_result->b_size - size);
390+
err = 0;
391+
goto done;
376392
}
393+
394+
/*
395+
* The area has not been written, clear mapped for read/bmap cases.
396+
* If so, it will be filled with zero without reading from disk.
397+
*/
398+
clear_buffer_mapped(bh_result);
377399
done:
378400
bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb);
401+
if (err < 0)
402+
clear_buffer_mapped(bh_result);
379403
unlock_ret:
380404
mutex_unlock(&sbi->s_lock);
381405
return err;

fs/exfat/super.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,6 @@ static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf)
6767
struct exfat_sb_info *sbi = EXFAT_SB(sb);
6868
unsigned long long id = huge_encode_dev(sb->s_bdev->bd_dev);
6969

70-
if (sbi->used_clusters == EXFAT_CLUSTERS_UNTRACKED) {
71-
mutex_lock(&sbi->s_lock);
72-
if (exfat_count_used_clusters(sb, &sbi->used_clusters)) {
73-
mutex_unlock(&sbi->s_lock);
74-
return -EIO;
75-
}
76-
mutex_unlock(&sbi->s_lock);
77-
}
78-
7970
buf->f_type = sb->s_magic;
8071
buf->f_bsize = sbi->cluster_size;
8172
buf->f_blocks = sbi->num_clusters - 2; /* clu 0 & 1 */
@@ -531,7 +522,6 @@ static int exfat_read_boot_sector(struct super_block *sb)
531522
sbi->vol_flags = le16_to_cpu(p_boot->vol_flags);
532523
sbi->vol_flags_persistent = sbi->vol_flags & (VOLUME_DIRTY | MEDIA_FAILURE);
533524
sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER;
534-
sbi->used_clusters = EXFAT_CLUSTERS_UNTRACKED;
535525

536526
/* check consistencies */
537527
if ((u64)sbi->num_FAT_sectors << p_boot->sect_size_bits <

0 commit comments

Comments
 (0)