diff options
| author | 2026-07-06 15:17:39 -0700 | |
|---|---|---|
| committer | 2026-07-14 10:25:39 -0700 | |
| commit | 56a4dbc90601689d013eaa5ce1b3d6a54bcff7c7 (patch) | |
| tree | d05c1ed70b6b4cb64e50d6e5390fca476379522d | |
| parent | hfs: fix error code when writing beyond volume capacity (diff) | |
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>
| -rw-r--r-- | fs/hfsplus/inode.c | 10 |
1 files changed, 9 insertions, 1 deletions
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); |
