mirror of
https://github.com/RhapsodiOS/RhapsodiOS.git
synced 2026-11-03 22:01:40 -07:00
[GH-ISSUE #59] kernel: mapped-file shrink then regrow loses retained data on UFS and resurrects stale data on msdosfs #54
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#54
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 16, 2026).
Original GitHub issue: https://github.com/RhapsodiOS/RhapsodiOS/issues/59
Symptom
A file that is written through a
MAP_SHAREDmapping, shrunk withftruncatewhile still mapped, unmapped, then grown back withftruncatecomes back wrong when read withread():Both reproduce the same way on the unmodified
issue-43kernel (mach_kernel.issue43) and on the #52–#55 repair kernel (260033acb, cksum 3500498149). They are older than those fixes. The same sequence done withwrite()instead of a mapping passes on FAT16. ext2fs passes it after #52's fix.Reproduce
vm/ext2_mmap_truncate_test.c(added in260033acb), on a scratch file of the filesystem under test:The test does this:
ftruncateit to 64 KiB (sparse).mmapitMAP_SHAREDand write a pattern to every byte.ftruncatetolength(20480 in the failing case) while still mapped.length. This step passes.munmap, thenftruncateback to 64 KiB,fsync,close.read()everything. Bytes belowlengthmust hold the pattern, bytes fromlengthup must be zero.Logs:
vm/work/issues52-55/res/ufs-regrow*.log,msdos-regrow-baseline.log,msdos-truncate.log,msdos-write-regrow.log(the passingwrite()variant).Where to look
ffs_truncate→mapfs_trunc/vnode_pager_setsize. The truncate must keep, and later write back, dirty mapped pages below the new EOF. Something discards them instead. Possibilities:length;munmap/fsync.Compare with ext2fs after #52's fix, which passes this test.
detruncand the regrowth path inmsdosfs_vnops.c(deextend). When the file grows again, the clusters, or the cached pages past the old EOF, must read as zero. Thewrite()path zeroes them; the mapped path leaves the old contents, either in the VM object's cached pages or in clusters that were not cleared.Found by the #52–#55 repair work (see
vm/filesystem-issues-52-55.mdin260033acb). Related: #41 (truncate of a mapped file), #52, #55.@raynorpat commented on GitHub (Oct 16, 2026):
Fixed on ffs-perf (merge
d6aad145fof branch issue-59).b0a796ecd, stale data past the cut (FAT16, and UFS too). The not-kernel-mapped branch ofmapfs_trunc(kern/mapfs.c~639) freed the pages pastround_page(length), but left the page holding the new end resident, still carrying what the mapping wrote past the cut. A newvno_flush_eof()writes that page back, stopping at the new EOF, and then frees it.2939f6a31, UFS lost the data below the cut.ffs_truncatecalledvnode_uncache(ffs_inode.c:311 and :342), which made the VM object non-persistent.vm_object_terminatethen freed the dirty mapped pages without writing them back. Those calls now run only without MACH_NBC, likeffs_write.44d06b87d: a stressmmap regrowtest.Two existing ext2 deadlocks surfaced under the stress suite's concurrent mmap load, while verifying this fix. Both are fixed in the same merge:
6d3b2c1a2:ext2fs_vget_internalkept the inode-table block busy acrossgetnewvnode. A recycled vnode's inactive was waiting on that same block.631eb5071:vnode_pageinsetnfspagereqonly aftervn_lock, so a pusher holding the vnode waited forever on the busy page.Verified on a kernel with these fixes plus a rebuilt driverkit (cksum 1566268189):
vm/ext2_mmap_truncate_test.cat all 4 lengths, and 28 regrow variants, pass on UFS, FAT16 and ext2.make check-mmappass.mmap/runtests -n 4passes on UFS and FAT16, and passes on ext2 in 3 of 4 runs, with no hangs.fsck -n,fsck_msdos -nande2fsck -fnare clean.Still open, tracked separately:
mmap syncread-back failure (zeros after offset 0x36) seen once under concurrent load.sync; umount; mounton UFS and FAT16. This happens on the unmodified kernel too.