mirror of
https://github.com/RhapsodiOS/RhapsodiOS.git
synced 2026-11-03 22:01:40 -07:00
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#74
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 30, 2026).
Original GitHub issue: https://github.com/RhapsodiOS/RhapsodiOS/issues/81
Originally assigned to: @raynorpat on GitHub.
Follow-ups from #78 (fixes
387d97d67anddc5864824, merged into ffs-perf in3d017f064). All three are insrc/kernel-7/kern/mapfs.c.1. Holders that don't hold the vnode lock can touch a freed vm_info
A forced unmount's
vm_info_freecan run while these still use the entry:mapfs_sync, betweenvm_info_unlock()andvmp_get(vmp)(~1590). It holds no use count yet, sovm_info_freeseesuse_count == 0and frees it.unmap_vnodeacross its blockingVOP_GETATTRand push (~509-548).unmap_vnodeon a NULLv_vm_info.vmp_invalidaterunning without a use count.2. The last
vmp_putcan be freed under itvmp_putdropsuse_countto 0 undervm_info_lock, unlocks, and then callslock_clear_recursive/lock_write_doneonvmp->lock. Ifvm_info_freetakesvm_info_lockin that gap, it seesuse_count == 0, doesn't mark the entry orphaned, andzfrees it. The putter then writes to freed memory.Waiting on
vmp->lockinvm_info_freeisn't obviously safe.remap_vnode'smapfs_memfree(vmp1, TRUE)can hold another file'svmp->lockacross a push that waits for that file's vnode lock, which the reclaiming thread holds.3. A forced reclaim of an open file leaks
When
map_count > 0,mapfs_uncacheskipsmapfs_memfree.vm_info_freethen frees (or orphans) the vm_info but leaves its mfs map window and VM object reference behind. This is unchanged from the stock kernel.@raynorpat commented on GitHub (Oct 30, 2026):
Fixed by
e8fac53e3(plusb545c56ad, a comment), merged into ffs-perf ina5e15760e.Lifetime rule: a thread may use a vm_info only while it holds one of two things:
vm_info_free.use_counttaken undervm_info_lock(vmp_pin). It must be taken fromv_vm_infobefore the thread first blocks, or fromvm_info_queuebeforevm_info_lockis dropped.Under
vm_info_lock,vm_info_freedequeues the entry and clearsv_vm_info. If nobody holds a pin, it frees the entry now throughvm_info_release(window, object reference, cred, zfree). Otherwise it marks it orphan, and the lastvmp_unpin, which is that caller's last touch, frees it.vmp_putnow unlocksvmp->lockfirst and unpins last, which closes item 2.Audit. These broke the rule and are fixed (
mapfs.clines from3d017f064):mapfs_sync1588-1591unmap_vnode481 and 508-550vmp_put871-894remap_vnode570 and 605-621mapfs_cache_trim1036-1041mapfs_cache_clear1061-1063mapfs_window_free1011-1014mapfs_io1292-1568vm_info_free337mapfs_fsync1635vmp_push_range2034The rest hold the vnode lock.
Why it can't deadlock:
vmp->lock.vm_info_freetakes onlyvm_info_lock,mapfs_invalidatedefers on a pinned entry, andmapfs_fsyncis skipped under VXLOCK.vm_info_releasenever pushes.The VXLOCK skip in
mapfs_fsyncapplies only to a forced reclaim of an active vnode. A mapped vnode's pager holds a vnode reference (vnode_pager.c:616), andgetnewvnodepanics on a free vnode with a non-zero count (vfs_subr.c:455), so an ordinary recycle never reaches it mapped. On the stock kernel a push there slept forever invn_lock(vfs_vnops.c:545-549) and wrote nothing. Unpushed pages of a forced reclaim are dropped, and writers get EIO.Verified:
unmap_vnodeacross GETATTR,vmp_puttail: panic "freed vm_info" vs no panic.v_vm_infovs skipped (the exec trap that followed is #84).umount -fhung in vclean →mapfs_fsync→vn_lockon its own VXLOCK, vs rc=0 ×3.write()plus shared-mmap rewrites, no fsync, 3200 files against desiredvnodes 1328, forced recycling, remount. ok=3200, bad=0 on both stock and fix, fsck clean.rp.sh×3 andrp2.sh×3 rc=0.check-fs,check-mmap,check-vmpass on UFS and NFS. Two all-category five-filesystem runs: no panic, NFS plain unmount clean, ext2/hfs/msdos fsck clean.Not caused by this change (stock behaviour, reproduced on stock):
msyncreturns EIO under vnode-lock contention:vnode_pageouttakes the lock with LK_NOWAIT and retries once (vnode_pager.c:897-918). 246/297 failures on stock, 250/291 with the fix.vinvalbuf→nfsfsync.Left open:
nfs_subs.c1405-1427 and 1488-1511 call memfree without a pin. An object is kept if a pageout is in flight at the reclaim.