mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
exfat: fix a large buffered write failing when the volume is nearly full
Commit82a81a7352("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 commit82a81a7352("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:82a81a7352("exfat: add iomap buffered I/O support") Cc: stable@vger.kernel.org Signed-off-by: Hengyu Liang <hengyul@cs.unc.edu> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
748ad4ba13
commit
73cababf93
|
|
@ -75,6 +75,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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user