mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 14:33:24 -04:00
hfsplus: fix error code when writing beyond volume capacity
The xfstests' test-case generic/564 fails for the case of HFS+ file system. Test-case expects that file system driver reports -EFBIG error code in the case if there is the effort to write beyond 8TiB. However, HFS+ file system driver returns -ENOSPC instead. The root cause is that hfsplus_fill_super() sets s_maxbytes as MAX_LFS_FILESIZE. VFS therefore considers the write position valid and calls into the filesystem. Because HFS+ does not support holes, cont_write_begin() zero-fills the entire intermediate range from the current end-of-file to the target offset. On a small test volume this exhausts free space long before any block-number overflow is detected, producing -ENOSPC instead of -EFBIG. This patch fixes the issue by adding a bounds check at the top of hfsplus_write_begin(). If the requested write position is at or beyond the actual capacity of the volume in bytes, return -EFBIG immediately before cont_write_begin() is entered and before any zero-fill I/O is attempted. sudo ./check generic/564 FSTYP -- hfsplus PLATFORM -- Linux/x86_64 hfsplus-testing-0001 7.2.0-rc1-dirty #50 SMP PREEMPT_DYNAMIC Fri Jul 3 16:22:27 PDT 2026 MKFS_OPTIONS -- /dev/loop51 MOUNT_OPTIONS -- /dev/loop51 /mnt/scratch generic/564 13s ... 43s Ran: generic/564 Passed all 1 tests cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> cc: Yangtao Li <frank.li@vivo.com> cc: linux-fsdevel@vger.kernel.org Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com> Link: https://lore.kernel.org/r/20260706221738.140271-2-slava@dubeyko.com Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
This commit is contained in:
@@ -43,11 +43,19 @@ int hfsplus_write_begin(const struct kiocb *iocb,
|
||||
unsigned len, struct folio **foliop,
|
||||
void **fsdata)
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
|
||||
loff_t total_capacity;
|
||||
int ret;
|
||||
|
||||
total_capacity = (loff_t)sbi->total_blocks << sbi->alloc_blksz_shift;
|
||||
|
||||
if (pos >= total_capacity)
|
||||
return -EFBIG;
|
||||
|
||||
ret = cont_write_begin(iocb, mapping, pos, len, foliop, fsdata,
|
||||
hfsplus_get_block,
|
||||
&HFSPLUS_I(mapping->host)->phys_size);
|
||||
&HFSPLUS_I(inode)->phys_size);
|
||||
if (unlikely(ret))
|
||||
hfsplus_write_failed(mapping, pos + len);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user