[PATCH] exfat: fix a large buffered write failing when the volume is nearly full
From: Hengyu Liang
Date: Sat Oct 10 2026 - 00:45:10 EST
Commit 82a81a7352bc ("exfat: add iomap buffered I/O support") made a
buffered write map the whole range of the write in one step, so the
clusters for all of it are allocated at once.
However, exfat_alloc_cluster() returns -ENOSPC when fewer clusters are
free than it is asked for. As of now, a write() that is larger than the
free space writes nothing and fails with ENOSPC, while it used to write
as much as fits and return a short count.
The issue can be reproduced with a 16M image made by mkfs.exfat that is
filled except for 256K:
mount -o loop /img /mnt
dd if=/dev/zero of=/mnt/hole bs=256k count=1
dd if=/dev/zero of=/mnt/fill bs=4k
rm /mnt/hole
dd if=/dev/zero of=/mnt/f bs=1M count=1
wc -c < /mnt/f
Before commit 82a81a7352bc ("exfat: add iomap buffered I/O support"),
the result is:
262144
After that commit, the result is:
0
This patch will map a single cluster when the clusters for the whole
range cannot be allocated, so that the write goes on until the volume is
full. Direct I/O is not changed, it still fails without writing as it
did before that commit.
Fixes: 82a81a7352bc ("exfat: add iomap buffered I/O support")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Hengyu Liang <hengyul@xxxxxxxxxx>
---
Direct I/O is left alone on purpose. exfat_alloc_cluster() could
instead take what is left when it is called with contig set, but direct
I/O uses the same path. As far as I can see, a large direct write would
then allocate and write those clusters and still fail with ENOSPC at
the next mapping, and the clusters would stay beyond i_size. Before
82a81a7352bc such a direct write also failed without writing.
Tested on v7.3-rc6 in QEMU with 512-byte, 4K and 32K clusters.
fsck.exfat is clean after several writers filled the volume. The patch
also applies to linux-next 20261009.
fs/exfat/iomap.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/fs/exfat/iomap.c b/fs/exfat/iomap.c
index 8911aa84a730..22facb240b85 100644
--- a/fs/exfat/iomap.c
+++ b/fs/exfat/iomap.c
@@ -74,6 +74,17 @@ static int __exfat_iomap_begin(struct inode *inode, loff_t offset, loff_t length
err = exfat_map_cluster(inode, exfat_bytes_to_cluster(sbi, offset),
&cluster, &num_clusters, may_alloc, &balloc);
+ if (err == -ENOSPC && !(flags & IOMAP_DIRECT)) {
+ /*
+ * There are not enough free clusters for the whole range. A
+ * buffered write can be short, so map what still fits.
+ */
+ num_clusters = 1;
+ err = exfat_map_cluster(inode,
+ exfat_bytes_to_cluster(sbi, offset),
+ &cluster, &num_clusters, may_alloc,
+ &balloc);
+ }
if (err)
goto out;
--
2.53.0