Skip to content

Conversation

@assembler-0
Copy link
Owner

@assembler-0 assembler-0 commented Oct 29, 2025

ACPI graceful shutdown and runtime mounts and umounts

Summary by CodeRabbit

  • New Features

    • Filesystem unmount support added across all supported filesystems; new VFS APIs to unmount single mounts or all mounts.
    • Mount and unmount shell commands for managing mounts from the shell.
    • Shutdown/reboot flow enhanced to perform orderly process termination and filesystem unmounting.
  • Chores

    • Removed deprecated fast allocation public APIs.
    • Disk image creation now uses a FAT filesystem.
    • Documentation updated (README).

@coderabbitai
Copy link

coderabbitai bot commented Oct 29, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

The PR adds ACPIResetProcedure and AcpiFindTable to the ACPI driver and updates shutdown/reboot flows to invoke reset/unmount steps. Filesystem drivers (EXT2, FAT1x, NTFS) gain public Unmount functions and are wired into a new VfsUmount and VfsUnmountAll API. Scheduler interfaces gain KillAllProcess variants with scheduler-specific implementations. Shell gains Mount/Unmount commands. MemPool.h removes FastAlloc/FastFree. Build changes switch a SataDisk image to FAT12 in CMake. README updates adjust language and build instructions. Public headers updated accordingly.

Poem

🐰 I nibble bytes and tidy trees,

Unmounting volumes with joyful ease,
I hush the processes, one, two, three,
ACPI sings a reset for me,
A reboot dawns — crisp, clean, and free! 🥕✨

Pre-merge checks

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title "Development" is a single word that provides no meaningful information about the changeset. It appears to be a branch name rather than a descriptive summary of the changes. While the PR description ("ACPI graceful shutdown and runtime mounts and umounts") accurately captures the main objectives, the title itself fails to convey any specific details about what was changed, making it impossible for someone scanning the commit history to understand the primary purpose of this PR based on the title alone.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2eb4af7 and f570445.

📒 Files selected for processing (11)
  • CMakeLists.txt (1 hunks)
  • README.md (2 hunks)
  • drivers/ACPI.c (3 hunks)
  • drivers/ACPI.h (1 hunks)
  • fs/EXT/Ext2.c (2 hunks)
  • fs/FAT/FAT1x.c (3 hunks)
  • fs/VFS.c (2 hunks)
  • kernel/sched/EEVDF.c (1 hunks)
  • kernel/sched/EEVDF.h (1 hunks)
  • kernel/sched/MLFQ.h (1 hunks)
  • kernel/sched/Scheduler.c (1 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
drivers/ACPI.c (1)

178-186: Avoid reinitializing the shutdown values array and guard FADT usage.

  • Move the shutdown values array out of the loop.
  • Null/zero‑guard g_fadt and pm1a_control_block before outw().

Suggested change:

-// Try multiple shutdown methods
-for (int i = 0; i < 4; i++) {
-    const uint16_t shutdown_values[] = {0x2000, 0x3C00, 0x1400, 0x0000};
-    PrintKernel("ACPI: Trying shutdown value 0x");
-    PrintKernelHex(shutdown_values[i]);
-    PrintKernel(" on port 0x");
-    PrintKernelHex(g_fadt->pm1a_control_block);
-    PrintKernel("\n");
-    
-    outw(g_fadt->pm1a_control_block, shutdown_values[i]);
-    
-    // Wait a bit
-    delay(10);
-}
+// Try multiple shutdown methods via PM1a
+static const uint16_t k_pm1_shutdown_values[4] = {0x2000, 0x3C00, 0x1400, 0x0000};
+if (!g_fadt || g_fadt->pm1a_control_block == 0) {
+    PrintKernelError("ACPI: FADT/PM1a control block unavailable; skipping PM1a shutdown\n");
+} else {
+    for (int i = 0; i < 4; i++) {
+        PrintKernel("ACPI: Trying shutdown value 0x");
+        PrintKernelHex(k_pm1_shutdown_values[i]);
+        PrintKernel(" on port 0x");
+        PrintKernelHex(g_fadt->pm1a_control_block);
+        PrintKernel("\n");
+        outw(g_fadt->pm1a_control_block, k_pm1_shutdown_values[i]);
+        delay(10);
+    }
+}
fs/EXT/Ext2.c (2)

32-47: Null deref in Ext2SetActive when device not yet mounted.

If g_ext2_by_dev[id] is NULL, dereferencing vol->lock will crash. Guard vol before checking its lock.

-    Ext2Volume* vol = g_ext2_by_dev[id];
-    if (!vol->lock) return;
+    Ext2Volume* vol = g_ext2_by_dev[id];
+    if (!vol || !vol->lock) { return; }

319-334: Based on my verification, the review comment's deadlock concern is valid and well-founded. I've confirmed three critical nested-lock deadlock sites in the codebase:

  1. Ext2WriteInode (line 295): Acquires write_lock, then calls Ext2WriteBlock (line 328) which tries to acquire write_lock again
  2. Ext2AllocateInode (line 656): Acquires write_lock, then calls Ext2WriteBlock (lines 673, 676) which try to acquire write_lock again
  3. Ext2AllocateBlock (line 693): Acquires write_lock, then calls Ext2WriteBlock (lines 710, 713) which try to acquire write_lock again

The diff provided in the review correctly addresses the Ext2WriteInode case by using BlockDeviceRead/Write directly while holding the write_lock. However, the review correctly notes that similar fixes are needed for Ext2AllocateInode and Ext2AllocateBlock as well.


Fix nested write-lock deadlocks in Ext2WriteInode, Ext2AllocateInode, and Ext2AllocateBlock.

Three functions acquire write_lock on volume.lock, then call Ext2WriteBlock (and Ext2ReadBlock in some cases) which attempt to acquire locks again, causing deadlock:

  • Ext2WriteInode (line 295): write_lock → Ext2WriteBlock (328)
  • Ext2AllocateInode (line 656): write_lock → Ext2WriteBlock (673, 676)
  • Ext2AllocateBlock (line 693): write_lock → Ext2WriteBlock (710, 713)

Use BlockDeviceRead/Write directly (with num_sectors = block_size / 512; lba = block * num_sectors) instead of Ext2ReadBlock/Ext2WriteBlock while holding write_lock. Apply this pattern to all three functions to eliminate nested locking.

-    // Read-modify-write the block containing the inode
-    if (Ext2ReadBlock(inode_table_block + block_offset, block_buffer) != 0) {
+    // Read-modify-write the block containing the inode (avoid nested locking)
+    uint32_t num_sectors = volume.block_size / 512;
+    uint32_t lba = (inode_table_block + block_offset) * num_sectors;
+    if (BlockDeviceRead(volume.device->id, lba, num_sectors, block_buffer) != 0) {
         KernelFree(block_buffer);
         rust_rwlock_write_unlock(volume.lock);
         return -1;
     }
     FastMemcpy(block_buffer + offset_in_block, inode, sizeof(Ext2Inode));
-    if (Ext2WriteBlock(inode_table_block + block_offset, block_buffer) != 0) {
+    if (BlockDeviceWrite(volume.device->id, lba, num_sectors, block_buffer) != 0) {
         KernelFree(block_buffer);
         rust_rwlock_write_unlock(volume.lock);
         return -1;
     }
fs/VFS.c (1)

376-399: VfsIsFile should not infer “file” from size > 0 (FAT).

This misclassifies zero-length files as non-files. Align with VfsIsDir pattern and FS-specific IsFile hooks. Based on learnings.

-        if (FastStrCmp(mount->fs_driver->name, "FAT1x") == 0) {
-            return Fat1xGetFileSize(local_path) > 0;
+        if (FastStrCmp(mount->fs_driver->name, "FAT1x") == 0) {
+            Fat1xSetActive(mount->device);
+            return Fat1xIsFile(local_path);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f177c06 and 2eb4af7.

📒 Files selected for processing (18)
  • drivers/ACPI.c (3 hunks)
  • fs/EXT/Ext2.c (2 hunks)
  • fs/EXT/Ext2.h (1 hunks)
  • fs/FAT/FAT1x.c (3 hunks)
  • fs/FAT/FAT1x.h (1 hunks)
  • fs/FileSystem.h (1 hunks)
  • fs/NTFS/NTFS.c (2 hunks)
  • fs/NTFS/NTFS.h (1 hunks)
  • fs/VFS.c (2 hunks)
  • fs/VFS.h (2 hunks)
  • include/Scheduler.h (1 hunks)
  • kernel/etc/Shell.c (5 hunks)
  • kernel/sched/EEVDF.c (1 hunks)
  • kernel/sched/EEVDF.h (1 hunks)
  • kernel/sched/MLFQ.c (1 hunks)
  • kernel/sched/MLFQ.h (1 hunks)
  • kernel/sched/Scheduler.c (1 hunks)
  • mm/MemPool.h (0 hunks)
💤 Files with no reviewable changes (1)
  • mm/MemPool.h
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-01T02:35:28.353Z
Learnt from: assembler-0
PR: assembler-0/VoidFrame#103
File: fs/VFS.c:331-335
Timestamp: 2025-09-01T02:35:28.353Z
Learning: VfsIsFile function was initially implemented as a placeholder that only checked for mount existence. The proper implementation should follow the same pattern as VfsIsDir: find mount, strip mount path, then use filesystem-specific functions to check if the path points to a file (FS_FILE for RAMFS, Fat12 functions for FAT12).

Applied to files:

  • fs/VFS.c
🧬 Code graph analysis (13)
fs/EXT/Ext2.h (1)
fs/EXT/Ext2.c (1)
  • Ext2Unmount (230-254)
kernel/sched/Scheduler.c (1)
kernel/sched/EEVDF.c (1)
  • EEVDFKillAllProcesses (1321-1328)
fs/FAT/FAT1x.h (1)
fs/FAT/FAT1x.c (1)
  • Fat1xUnmount (102-133)
kernel/sched/EEVDF.h (1)
kernel/sched/EEVDF.c (1)
  • EEVDFKillAllProcesses (1321-1328)
fs/NTFS/NTFS.c (1)
kernel/atomic/rust/src/ffi.rs (1)
  • rust_rwlock_free (168-179)
drivers/ACPI.c (4)
fs/VFS.c (1)
  • VfsUnmountAll (79-86)
kernel/etc/Console.c (1)
  • PrintKernelSuccess (225-230)
kernel/sched/Scheduler.c (1)
  • KillAllProcess (88-96)
include/Io.h (2)
  • outb (6-8)
  • outw (16-18)
kernel/sched/MLFQ.h (1)
kernel/sched/MLFQ.c (1)
  • MLFQKillAllProcesses (1922-1929)
fs/VFS.c (5)
fs/VFRFS.c (1)
  • FsDelete (321-331)
fs/NTFS/NTFS.c (1)
  • NtfsUnmount (151-171)
fs/FileSystem.c (1)
  • FileSystemRegister (13-22)
fs/FAT/FAT1x.c (1)
  • Fat1xUnmount (102-133)
fs/EXT/Ext2.c (1)
  • Ext2Unmount (230-254)
include/Scheduler.h (1)
kernel/sched/Scheduler.c (1)
  • KillAllProcess (88-96)
fs/NTFS/NTFS.h (1)
fs/NTFS/NTFS.c (1)
  • NtfsUnmount (151-171)
kernel/etc/Shell.c (8)
kernel/etc/Console.c (1)
  • PrintKernel (198-211)
fs/BlockDevice.c (1)
  • SearchBlockDevice (104-111)
kernel/etc/Format.c (1)
  • FormatA (233-239)
kernel/etc/StringOps.c (1)
  • FastStrCmp (39-49)
fs/FAT/FAT1x.c (1)
  • Fat1xMount (46-100)
fs/EXT/Ext2.c (1)
  • Ext2Mount (123-228)
fs/NTFS/NTFS.c (1)
  • NtfsMount (48-149)
fs/VFS.c (1)
  • VfsUmount (61-77)
fs/VFS.h (1)
fs/VFS.c (3)
  • VfsUmount (61-77)
  • VfsStripMount (155-175)
  • VfsUnmountAll (79-86)
fs/EXT/Ext2.c (2)
kernel/etc/Console.c (1)
  • PrintKernelSuccess (225-230)
kernel/atomic/rust/src/ffi.rs (2)
  • rust_rwlock_write_unlock (203-207)
  • rust_rwlock_free (168-179)
🪛 Clang (14.0.6)
fs/NTFS/NTFS.c

[warning] 46-46: variable 'ntfs_driver' is non-const and globally accessible, consider making it const

(cppcoreguidelines-avoid-non-const-global-variables)


[warning] 152-152: statement should be inside braces

(readability-braces-around-statements)


[warning] 153-153: variable name 'id' is too short, expected at least 3 characters

(readability-identifier-length)


[warning] 154-154: statement should be inside braces

(readability-braces-around-statements)


[warning] 156-156: variable 'vol' is not initialized

(cppcoreguidelines-init-variables)


[warning] 157-157: statement should be inside braces

(readability-braces-around-statements)

drivers/ACPI.c

[warning] 192-192: 0xB004 is a magic number; consider replacing it with a named constant

(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)


[warning] 192-192: 0x2000 is a magic number; consider replacing it with a named constant

(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)

fs/FAT/FAT1x.c

[warning] 44-44: variable 'fat_driver' is non-const and globally accessible, consider making it const

(cppcoreguidelines-avoid-non-const-global-variables)


[warning] 102-102: parameter 'device' is unused

(misc-unused-parameters)


[warning] 103-103: statement should be inside braces

(readability-braces-around-statements)


[warning] 104-104: variable 'id' is not initialized

(cppcoreguidelines-init-variables)


[warning] 104-104: variable name 'id' is too short, expected at least 3 characters

(readability-identifier-length)


[warning] 105-105: statement should be inside braces

(readability-braces-around-statements)


[warning] 107-107: variable 'vol' is not initialized

(cppcoreguidelines-init-variables)


[warning] 108-108: statement should be inside braces

(readability-braces-around-statements)

kernel/etc/Shell.c

[warning] 1203-1203: statement should be inside braces

(readability-braces-around-statements)


[warning] 1204-1204: statement should be inside braces

(readability-braces-around-statements)


[warning] 1216-1216: 64 is a magic number; consider replacing it with a named constant

(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)


[warning] 1219-1219: repeated branch in conditional chain

(bugprone-branch-clone)


[note] 1221-1221: end of the original

(clang)


[note] 1221-1221: clone 1 starts here

(clang)


[note] 1223-1223: clone 2 starts here

(clang)


[warning] 1240-1240: 256 is a magic number; consider replacing it with a named constant

(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)


[warning] 1241-1241: 256 is a magic number; consider replacing it with a named constant

(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)

kernel/sched/MLFQ.c

[warning] 1924-1924: variable name 'p' is too short, expected at least 3 characters

(readability-identifier-length)

fs/EXT/Ext2.c

[warning] 121-121: variable 'ext2_driver' is non-const and globally accessible, consider making it const

(cppcoreguidelines-avoid-non-const-global-variables)


[warning] 231-231: statement should be inside braces

(readability-braces-around-statements)


[warning] 232-232: variable name 'id' is too short, expected at least 3 characters

(readability-identifier-length)


[warning] 233-233: statement should be inside braces

(readability-braces-around-statements)


[warning] 236-236: statement should be inside braces

(readability-braces-around-statements)

🔇 Additional comments (6)
drivers/ACPI.c (1)

182-186: Guard all uses of g_fadt and confirm call context for ACPIResetProcedure in reboot.

  • Add NULL checks before dereferencing g_fadt in both shutdown and reboot paths.
  • Ensure ACPIResetProcedure is invoked from a safe (non‑terminatable) kernel context or exclude the current PID from kill‑all.

Would you like a patch to exclude the current PID from KillAll and to early‑out to Bochs fallback when g_fadt is NULL/invalid?

Also applies to: 198-200

kernel/sched/EEVDF.h (1)

204-205: LGTM; consistent with EEVDF.c implementation.

kernel/sched/EEVDF.c (1)

1321-1328: Verify termination queue capacity for bulk termination.

The review comment is accurate. The termination queue implementation uses a circular buffer with capacity check if (term_queue_count >= EEVDF_MAX_PROCESSES) triggering a panic, which constrains usable capacity to 63 items. However, EEVDFKillAllProcesses iterates through all EEVDF_MAX_PROCESSES (64) slots and calls EEVDFASTerminate for each active process, and EEVDFASTerminate calls AddToTerminationQueueAtomic(slot) to enqueue each terminating process.

If all 64 process slots are active during shutdown and no concurrent dequeuing occurs, the 64th enqueue will trigger a panic. This edge case requires confirmation: verify whether cleanup runs concurrently during EEVDFKillAllProcesses, whether graceful degradation is preferable to panic, and that your shutdown/reboot sequence handles this scenario safely.

fs/NTFS/NTFS.c (1)

151-171: LGTM!

The NtfsUnmount implementation correctly handles resource cleanup: validates the device, clears the active mount reference, frees the lock, deallocates the volume structure, and clears the registry entry. The implementation follows the same pattern as other filesystem unmount functions.

fs/EXT/Ext2.c (1)

225-225: LGTM: clearer success signal on mount.

The success badge improves UX and aligns with Console helpers.

fs/VFS.c (1)

61-77: Based on my verification, I can now provide the rewritten review comment:


Handle FsDelete failure and clean up stale mount fields; clarify mount point deletion semantics.

Two issues:

  1. FsDelete return value ignored at line 72—can fail silently
  2. Mount struct fields remain uncleared after unmount, inconsistent with VfsInit which zeroes only the active flag

Regarding mount point deletion: the proposed change moves FsDelete outside the driver conditional (currently only called when driver has unmount hook), which changes behavior for virtual filesystems like DevFS. This is an architectural decision—clarify whether mount point directories should always be cleaned up, or only for drivers providing unmount logic.

 int VfsUmount(const char* path) {
     VfsMountStruct* mount = VfsFindMount(path);
     if (!mount) { return -1; }

     if (mount->fs_driver && mount->fs_driver->unmount) {
         int result = mount->fs_driver->unmount(mount->device);
         if (result != 0) { return result; }
+        int del_res = FsDelete(mount->mount_point);
+        if (del_res != 0) {
+            PrintKernel("VFS: Warning: failed to remove mount point\n");
+        }
     }

     mount->active = 0;
+    mount->device = NULL;
+    mount->fs_driver = NULL;
+    mount->mount_point[0] = '\0';
     return 0;
 }

Before proceeding, confirm:

  • Should mount point directories be deleted for all unmounts, or only when driver provides unmount cleanup?
  • Should DevFS (/Devices) be exempted from deletion at shutdown?

@assembler-0 assembler-0 merged commit 0f3c5b0 into main Oct 29, 2025
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants