mirror of
https://github.com/RhapsodiOS/RhapsodiOS.git
synced 2026-11-03 22:01:40 -07:00
[GH-ISSUE #65] msdosfs: concurrent writes corrupt FAT16 data and the FAT (EINVAL, wrong blocks, lost clusters) and panic 'extendfile: pcbmap' #59
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#59
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 19, 2026).
Original GitHub issue: https://github.com/RhapsodiOS/RhapsodiOS/issues/65
Symptom
Under the stress suite's concurrent
fsload, a FAT16 volume on the i386 kernel corrupts data and its FAT. Underfsandmmapload together it panics. Seen across five harness runs between 2026-10-16 and 2026-10-19, on the issue58 kernel (ffs-perf with #52-#56 and #58) and on the #60 kernel (ffs-perf8235b390f: plus #59 and #60):STRESS fs fsync FAIL what=block off=0x3800 want=94b44c7b... got=604ab9f3..., a block read back with someone else's data.STRESS fs rw FAIL reason="read: EINVAL"andreason="write: EINVAL", several workers and seeds;STRESS mmap trunc FAIL reason="ftruncate: EINVAL".fsck_msdos -nreports lost cluster chains;... starts with free cluster,has entries after end of directory, and a garbage name.panic: extendfile: pcbmap, twice, both withfsandmmapin the same run. Runningfsalone ormmapalone did not panic.Reproduce
The phase 4 harness (branch
stress-phase4):This formats partition c of a 3-partition targets disk (512-byte NeXT label, 128 MB) with the guest-built
newfs_msdos(FAT16), mounts it at/mnt/msdos, runsrun -s 4 -d /mnt/msdos 1 fs mmapand then fscks it. Use--cats fsfor the corruption without the panic.Evidence:
vm/work/ffsbench/runs/p4-accept/stress-0/:msdos.*.out,msdos.summary, the targets disk image,stressfs.outp4-msfs/(fs only),p4-msmm/(mmap only)p4-fs3/andp4-fs4/(the panics; serial logs)Where to look
The panic:
extendfileinbsd/msdosfs/msdosfs_fat.c, wherepcbmapfails while the file is being extended.Shared state: the corruption suggests concurrent cluster allocation or FAT updates aren't serialised. Several workers extend different files, and
fsyncthen reads back a block that now belongs to another file.Recent changes to compare:
260033acb: rename locking,msdosfs_lookup, pageout and size);883ed93c2).Check
extendfile/clusteralloclocking against concurrentdeextendanddetrunc.Related: #54, #55, #58. Found by stress suite phase 4's
--fstargets.@raynorpat commented on GitHub (Oct 20, 2026):
Fixed by
56d820206(kernel: recheck the buffer hash after getnewbuf sleeps in getblk, so two threads cannot make duplicate buffers for one block), merged into ffs-perf in306504515.Not #71: it reproduced on the first run on a kernel with the FSAVE workaround (ffs-perf
4fd6d07b6).Cause: the buffer cache, not msdosfs.
getblk()(bsd/vfs/vfs_bio.c~698) calledgetnewbuf(), which can sleep writing out a delayed buffer, and never re-checked the hash afterwards.allocbuf(), which can also sleep, before the new buffer was findable (block number and vnode not yet set).Evidence:
FAT[6144](the first entry of FAT block 25) read back free right afterfatchainhad written a contiguous run through it.pcbmapthen followed the broken chain to cluster 0, which is inside the root directory: hence the garbage names and "entries after end of directory".GETBLK raced) caught the race on FAT blocks 1, 9, 57, 177, 185 and 225.extendfile: pcbmappanic and the lost chains are the same lost update.Fix:
getnewbuf(); if the block appeared meanwhile, drop the new buffer and start over.allocbuf(), so other threads wait on it instead of duplicating it.The race is in code every buffer-cache filesystem shares, so UFS, ext2 and HFS benefit too.
Verified on the fixed kernel (cksum 1947222504):
fs mmapat seeds 4, 9 and 7: PASS=28, FAIL=0, UNSUP=2 each, fsck_msdos clean, no panic.Note: msdos
fs rwpasses but takes about 1000 s on this host, over the harness's default 600 s per-test watchdog, so default--fs msdosruns still report anrwtimeout. That's a speed matter, not this bug.