From 56a4dbc90601689d013eaa5ce1b3d6a54bcff7c7 Mon Sep 17 00:00:00 2001 From: Viacheslav Dubeyko Date: Mon, 6 Jul 2026 15:17:39 -0700 Subject: [PATCH] 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 cc: Yangtao Li cc: linux-fsdevel@vger.kernel.org Signed-off-by: Viacheslav Dubeyko Link: https://lore.kernel.org/r/20260706221738.140271-2-slava@dubeyko.com Signed-off-by: Viacheslav Dubeyko --- fs/hfsplus/inode.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 1c57c873f05d..2ce6de574fa6 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -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);