linux/fs/hfsplus
Viacheslav Dubeyko 66e2f3c1ae hfsplus: fix volume corruption issue for generic/101
[ Upstream commit 3f04ee216b ]

The xfstests' test-case generic/101 leaves HFS+ volume
in corrupted state:

sudo ./check generic/101
FSTYP -- hfsplus
PLATFORM -- Linux/x86_64 hfsplus-testing-0001 6.17.0-rc1+ #4 SMP PREEMPT_DYNAMIC Wed Oct 1 15:02:44 PDT 2025
MKFS_OPTIONS -- /dev/loop51
MOUNT_OPTIONS -- /dev/loop51 /mnt/scratch

generic/101 _check_generic_filesystem: filesystem on /dev/loop51 is inconsistent
(see XFSTESTS-2/xfstests-dev/results//generic/101.full for details)

Ran: generic/101
Failures: generic/101
Failed 1 of 1 tests

sudo fsck.hfsplus -d /dev/loop51
** /dev/loop51
Using cacheBlockSize=32K cacheTotalBlock=1024 cacheSize=32768K.
Executing fsck_hfs (version 540.1-Linux).
** Checking non-journaled HFS Plus Volume.
The volume name is untitled
** Checking extents overflow file.
** Checking catalog file.
** Checking multi-linked files.
** Checking catalog hierarchy.
** Checking extended attributes file.
** Checking volume bitmap.
** Checking volume information.
Invalid volume free block count
(It should be 2614350 instead of 2614382)
Verify Status: VIStat = 0x8000, ABTStat = 0x0000 EBTStat = 0x0000
CBTStat = 0x0000 CatStat = 0x00000000
** Repairing volume.
** Rechecking volume.
** Checking non-journaled HFS Plus Volume.
The volume name is untitled
** Checking extents overflow file.
** Checking catalog file.
** Checking multi-linked files.
** Checking catalog hierarchy.
** Checking extended attributes file.
** Checking volume bitmap.
** Checking volume information.
** The volume untitled was repaired successfully.

This test executes such steps: "Test that if we truncate a file
to a smaller size, then truncate it to its original size or
a larger size, then fsyncing it and a power failure happens,
the file will have the range [first_truncate_size, last_size[ with
all bytes having a value of 0x00 if we read it the next time
the filesystem is mounted.".

HFS+ keeps volume's free block count in the superblock.
However, hfsplus_file_fsync() doesn't store superblock's
content. As a result, superblock contains not correct
value of free blocks if a power failure happens.

This patch adds functionality of saving superblock's
content during hfsplus_file_fsync() call.

sudo ./check generic/101
FSTYP         -- hfsplus
PLATFORM      -- Linux/x86_64 hfsplus-testing-0001 6.18.0-rc3+ #96 SMP PREEMPT_DYNAMIC Wed Nov 19 12:47:37 PST 2025
MKFS_OPTIONS  -- /dev/loop51
MOUNT_OPTIONS -- /dev/loop51 /mnt/scratch

generic/101 32s ...  30s
Ran: generic/101
Passed all 1 tests

sudo fsck.hfsplus -d /dev/loop51
** /dev/loop51
	Using cacheBlockSize=32K cacheTotalBlock=1024 cacheSize=32768K.
   Executing fsck_hfs (version 540.1-Linux).
** Checking non-journaled HFS Plus Volume.
   The volume name is untitled
** Checking extents overflow file.
** Checking catalog file.
** Checking multi-linked files.
** Checking catalog hierarchy.
** Checking extended attributes file.
** Checking volume bitmap.
** Checking volume information.
** The volume untitled appears to be OK.

Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
cc: Yangtao Li <frank.li@vivo.com>
cc: linux-fsdevel@vger.kernel.org
Link: https://lore.kernel.org/r/20251119223219.1824434-1-slava@dubeyko.com
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
History 2026-01-02 12:56:41 +01:00
..
attributes.c hfs/hfsplus: rework debug output subsystem 2025-09-24 16:30:34 -07:00
bfind.c hfs/hfsplus: rework debug output subsystem 2025-09-24 16:30:34 -07:00
bitmap.c hfs/hfsplus: rework debug output subsystem 2025-09-24 16:30:34 -07:00
bnode.c hfsplus: fix missing hfs_bnode_get() in __hfs_bnode_create 2026-01-02 12:56:40 +01:00
brec.c hfs/hfsplus: rework debug output subsystem 2025-09-24 16:30:34 -07:00
btree.c hfs/hfsplus: rework debug output subsystem 2025-09-24 16:30:34 -07:00
catalog.c hfs/hfsplus: rework debug output subsystem 2025-09-24 16:30:34 -07:00
dir.c hfsplus: fix volume corruption issue for generic/073 2026-01-02 12:56:40 +01:00
extents.c hfs/hfsplus: rework debug output subsystem 2025-09-24 16:30:34 -07:00
hfsplus_fs.h hfsplus: fix volume corruption issue for generic/101 2026-01-02 12:56:41 +01:00
hfsplus_raw.h hfsplus: use struct_group_attr() for memcpy() region 2022-01-20 08:52:54 +02:00
inode.c hfsplus: fix volume corruption issue for generic/101 2026-01-02 12:56:41 +01:00
ioctl.c vfs: rename parent_ino to d_parent_ino and make it use RCU 2024-06-27 18:34:21 +02:00
Kconfig fs: add CONFIG_BUFFER_HEAD 2023-08-02 09:13:09 -06:00
Makefile hfsplus: drop ACL support 2018-08-22 10:52:50 -07:00
options.c hfsplus: convert hfsplus to use the new mount api 2024-10-08 14:41:50 +02:00
part_tbl.c fs/hfsplus: Use the enum req_op and blk_opf_t types 2022-07-14 12:14:32 -06:00
super.c hfsplus: fix volume corruption issue for generic/101 2026-01-02 12:56:41 +01:00
tables.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
unicode.c hfsplus: fix slab-out-of-bounds read in hfsplus_strcasecmp() 2025-09-22 15:11:33 -07:00
wrapper.c hfsplus: use bdev_rw_virt in hfsplus_submit_bio 2025-05-07 07:31:08 -06:00
xattr.c hfs/hfsplus: rework debug output subsystem 2025-09-24 16:30:34 -07:00
xattr.h hfsplus: move hfsplus_xattr_handlers to .rodata 2023-10-09 16:24:19 +02:00
xattr_security.c fs: port xattr to mnt_idmap 2023-01-19 09:24:28 +01:00
xattr_trusted.c fs: port xattr to mnt_idmap 2023-01-19 09:24:28 +01:00
xattr_user.c fs: port xattr to mnt_idmap 2023-01-19 09:24:28 +01:00