From c917af06290e1e2b9e0a36fb03406b1e7e8acfd5 Mon Sep 17 00:00:00 2001 From: Daniel Hammer Date: Sat, 15 Aug 2026 11:21:14 +0200 Subject: [PATCH] feat: login - write system log to disk (0:/os/logs/montaukos) during shutdown, limit disk flush stage to non-ramdisk storage devices --- kernel/src/Api/BuildNo.hpp | 2 +- programs/src/login/login_shutdown.cpp | 59 ++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/kernel/src/Api/BuildNo.hpp b/kernel/src/Api/BuildNo.hpp index d750c2c..4d43800 100644 --- a/kernel/src/Api/BuildNo.hpp +++ b/kernel/src/Api/BuildNo.hpp @@ -12,4 +12,4 @@ #pragma once -#define MONTAUK_BUILD_NUMBER 143 +#define MONTAUK_BUILD_NUMBER 149 diff --git a/programs/src/login/login_shutdown.cpp b/programs/src/login/login_shutdown.cpp index 0fba94c..d00fe77 100644 --- a/programs/src/login/login_shutdown.cpp +++ b/programs/src/login/login_shutdown.cpp @@ -9,6 +9,11 @@ using namespace gui; +bool volume0_is_persistent() { + if (montauk::drivekind(0) == 0) return false; + return true; +} + // Minimum time each shutdown stage stays on screen, so the status message is // readable even when the underlying work completes near-instantly. static constexpr uint64_t STAGE_MIN_VISIBLE_MS = 600; @@ -23,6 +28,7 @@ static constexpr uint64_t STAGE_MIN_VISIBLE_MS = 600; // wedged storage controller hits this bound. static constexpr uint64_t BT_STAGE_TIMEOUT_MS = 4000; static constexpr uint64_t FS_STAGE_TIMEOUT_MS = 10000; +static constexpr uint64_t LOG_WRITE_TIMEOUT_MS = 10000; void draw_shutdown_screen(LoginState* ls, const char* heading, const char* status) { Framebuffer& fb = ls->fb; @@ -171,6 +177,39 @@ void stage_disconnect_bluetooth() { } } +static bool path_is_file(const char* path) { + montauk::abi::FileStat st; + if (montauk::stat(path, &st) < 0) return false; + + return !st.isDir; +} + +#define LOG_READ_SIZE 65536 + +// Write the system log to a file on disk +void stage_save_log() { + // Edge case - 0:/os/logs exists and is a file + if (path_is_file("0:/os/logs")) + return; + + montauk::fmkdir("0:/os/logs"); + + // Clear any existing montaukos log + montauk::fdelete("0:/os/logs/montaukos"); + + int handle = montauk::fcreate("0:/os/logs/montaukos"); + if (handle < 0) + return; + + uint8_t* syslog_buf = (uint8_t*)montauk::malloc(LOG_READ_SIZE); + int n = montauk::read_log((char *)syslog_buf, LOG_READ_SIZE); + + int result = montauk::fwrite(handle, syslog_buf, 0, n); + + montauk::close(handle); + montauk::mfree(syslog_buf); +} + void stage_flush_filesystems() { montauk::fs_sync(); } @@ -193,13 +232,23 @@ void perform_graceful_shutdown(LoginState* ls, int action) { } } - // ==== Stage 2: flush writes and unmount filesystems ==== - show_stage(ls, heading, "Flushing file systems..."); - if (!run_stage(stage_flush_filesystems, FS_STAGE_TIMEOUT_MS)) { - show_stage(ls, heading, "Storage is unresponsive, continuing..."); + // No need to save log files or flush to disk if volume 0 is a ramdisk anyway + if (volume0_is_persistent()) { + // ==== Stage 2: write system log to disk ==== + show_stage(ls, heading, "Saving system log..."); + if (!run_stage(stage_save_log, LOG_WRITE_TIMEOUT_MS)) { + show_stage(ls, heading, "Log save is unresponsive, continuing..."); + } + + // ==== Stage 3: flush writes and unmount filesystems ==== + show_stage(ls, heading, "Flushing file systems..."); + if (!run_stage(stage_flush_filesystems, FS_STAGE_TIMEOUT_MS)) { + show_stage(ls, heading, "Storage is unresponsive, continuing..."); + } } - // ==== Stage 3: dispatch the ACPI power-off / reset ==== + + // ==== Stage 4: dispatch the ACPI power-off / reset ==== show_stage(ls, heading, rebooting ? "Restarting now..." : "Powering off..."); if (rebooting) { montauk::reset();