]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commit
kernel: add VFS spinlock (g_vfs_lock) to fix SMP mount-table races
authorTulio A M Mendes <[email protected]>
Mon, 4 May 2026 04:41:13 +0000 (01:41 -0300)
committerTulio A M Mendes <[email protected]>
Mon, 4 May 2026 23:52:08 +0000 (20:52 -0300)
commite93e60ca6ca9695e60f8b3bce027b9d74e1b5e77
tree6ae68d22f47fa14385a6b40e007b098b97e7b367
parent38e7aa5baddbc84ba23bd96ed3427085f53f788e
kernel: add VFS spinlock (g_vfs_lock) to fix SMP mount-table races

The VFS mount table (g_mounts[], g_mount_count, fs_root) had zero
locking protection. On SMP (4 CPUs), concurrent access during
pivot_root/mount/umount2 corrupted the mount table, causing:
- Mount points disappearing: vfs_umount shifts array entries while
  another CPU's vfs_lookup iterates, skipping/duplicating entries
- Sporadic QEMU reboot: corrupted fs_node_t* pointer from torn
  reads causes kernel page fault -> triple fault -> reboot

Fix:
- Add spinlock_t g_vfs_lock in fs.c protecting fs_root, g_mounts[],
  and g_mount_count
- Create _nolock variants (vfs_mount_nolock, vfs_umount_nolock) for
  compound operations that need atomicity across multiple mutations
- Public vfs_mount/vfs_umount acquire the lock automatically
- vfs_lookup_depth snapshots mount table under lock before traversal
- SYSCALL_PIVOT_ROOT holds g_vfs_lock across the entire compound
  mutation (fs_root update + two vfs_mount_nolock calls)
- Export g_vfs_lock and _nolock variants in fs.h

Also:
- fulltest pivot_root test: undo pivot_root in child before exit,
  verify /dev/null accessible after undo
- ulibc strrchr: add null-pointer guard (cppcheck ctunullpointer)
- fulltest: struct init {0} instead of {{0}} (cppcheck uninitvar)
include/fs.h
src/kernel/fs.c
src/kernel/syscall.c
user/cmds/fulltest/fulltest.c
user/ulibc/src/string.c