mirror of
https://github.com/RhapsodiOS/RhapsodiOS.git
synced 2026-11-03 22:01:40 -07:00
[GH-ISSUE #76] hfs: hfs_reclaim follows a stale h_fork when a complex node is reclaimed and panics at unmount #69
Labels
No labels
bug
documentation
enhancement
enhancement
good first issue
help wanted
help wanted
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
github-starred/RhapsodiOS#69
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @raynorpat on GitHub (Oct 20, 2026).
Original GitHub issue: https://github.com/RhapsodiOS/RhapsodiOS/issues/76
Symptom
ffsbench stress --fs hfswith all categories (seed 75) panics on the combined ffs-perf kernel (f68d4802c) at the unmount step, 3 of 3 runs:The faulting address is b000d4c1. Backtrace: unmount → dounmount → hfs_unmount → vflush → vgonel → vclean → hfs_reclaim.
Where
bsd/hfs/hfs_vnodeops.c~3423, the VCPLX branch:VTOH(VTOH(tp)->h_sibling)->h_relative = NULL. Heretp = hp->h_meta->h_forkis a fork vnode that has already been reclaimed, and itsh_siblingholds garbage (0xf000d445). The fork reclaim path only updatesh_meta->h_forkwhileh_usecount > 0, so after the last fork goes the complex node probably still points at it.On the base kernel (
4fd6d07b6) the same run doesn't panic but reports "umount failed": before #73,kernel_recover_threadhid the kernel fault. The HFS sources didn't change in this range.Logs:
vm/work/ffsbench/runs/combined*,vm/work/combined-retest/(pan.pygdbstub dump).@raynorpat commented on GitHub (Oct 21, 2026):
Fixed by
fa8183e56and23a37779f, merged into ffs-perf in966dc5243.Root cause (
hfs_vnodeops.chfs_reclaim, ~3349 before the fix):VREG/VLNKvnodes went through the branch that releases a fork.hfs_createrejects other types only under#if DIAGNOSTIC, sobind()of an AF_UNIX socket on HFS (net unix) creates a data fork with v_typeVSOCK(hfs_makenode).h_fork/h_relative, a meta use count that never dropped, and a reference that was never released.umount -fthen reclaimed the complex node, which followed the dead fork (v_data 0; the garbageh_siblingis BIOS vector 15 from address 0x3c) at ~3423.h_forkvnode reused by another file before the crash, so this was corrupting other nodes during normal use too.Fix:
fa8183e56: forks are now chosen by fork type (v_type != VNON && H_FORKTYPE != kDirCmplx), not vnode type.23a37779f: the last fork reclaimed clearsh_fork. On a forced unmount that reclaims the complex node first, the meta is left to the last fork, which frees it.Verified on the fixed kernel (cksum 3049947097):
--fs hfs --cats net: panicked on the combined kernel; passes now, 14 PASS, fsck clean.Left open: a socket file whose vnode was recycled and is looked up again gets VBAD for both its fork and its complex node. The complex node then leaks its meta, a small leak with no crash. Rejecting socket nodes in
hfs_createoutright would stop it but makebind()on HFS fail.