Files
fds-os/docs/developer/m10-validation.md
T
2026-09-22 13:23:34 +08:00

7.0 KiB
Raw Blame History

M10 shutdown validation

Development reference and historical context. For current operating instructions, use the user manual. Acceptance applies only to the source and artifacts identified in each record.

Shutdown usage · Implementation ledger

M10 software acceptance passed on 2026-09-21 in isolated ARM virtual machines. The complete shutdown suite, CLI packaging and earlier-milestone regressions passed. Physical Pi timing, flash-controller durability, power rails and battery behavior remain deferred.

Verified shutdown behavior

The ordinary FDS user can request fds poweroff or fds reboot. New cartridge operations freeze before the daemon stops the desktop, managed programs and networking. The original DATA filesystem descriptor checks writeback, the filesystem becomes read-only, a second check catches remount writeback, and normal unmount completes before native s6 stops the remaining services and halts or reboots. Dasung remains supervised until that final service stop.

make power-test passed all six cases in out/m10-vm.tituqzh7/:

Case Observed result VM preparation-to-kernel-action time
Idle Ordinary-user poweroff; unprivileged internal hook refused 540.733 ms
Active workload GUI, DHCP and TERM-ignoring descendants stopped; DATA verified; actual reboot 1835.329 ms
Direct native poweroff Busy DATA blocks the native hook until resolved; cancellation refused 414.091 ms
Active media preview Shutdown and new confirmation refused; cancellation leaves disk unchanged 289.099 ms after retry
Crashed DATA service Same insertion stays quarantined across further restarts; no false SAFE 281.307 ms after removing fixture
Attached-device writeback error Real EIO retained across restarts; SAFE and shutdown refused 344.777 ms after removing fixture

These are measurements inside generic QEMU with the Pi kernel, not Pi or physical power-off benchmarks. They do not establish the sub-second idle or 1.5-second normal-DATA hardware targets. The workload deliberately ignores TERM, so the manager must wait its bounded termination deadline and confirm actual exit before proceeding.

Each case records ordered CLOCK_BOOTTIME events and captures the final native shutdown record. The test waits for the kernel's halt/reboot message and QEMU's successful exit; closing the emulator does not count as a completed shutdown. The full command log is out/logs/m10-final-power.log.

DATA integrity and failure handling

The workload writes at least 128 MiB through a rotating 64 MiB file. After reboot, independent host e2fsck finds a clean filesystem, SHA-256 matches all 64 MiB, and an ordinary-user marker retains its exact contents. Open writable descriptors and a shell working directory both block shutdown. Explicit resume enables new operations but does not recreate stopped jobs.

Before writable activation, a root-private insertion record is created under /run/fds/data-sessions. A service crash cannot discard the original descriptor's writeback history and then issue SAFE based on a fresh descriptor. The same insertion becomes read-only and quarantined; a known error retains its diagnostic. Records survive service restarts during this boot, not power loss or a different insertion. The separate DATA regression passed in out/m7-vm.vmhkmyqk/.

The writeback test uses QEMU's blkdebug to return persistent EIO for writes to a known allocated file block. GPT, manifest and journal metadata remain outside that injected sector. The device stays attached; Linux reports a real writeback error and syncfs fails. The daemon refuses eject, keeps the fault after restart, and blocks shutdown through another restart. No filesystem-cleanliness claim is made for this deliberately damaged image. Removing the test fixture merely lets the remaining system shut down; it never turns the failed insertion SAFE.

See QEMU's fault-injection documentation. A one-shot fault is insufficient evidence by itself because the guest may retry it successfully; the acceptance case verifies the actual guest-visible EIO.

Native guard and dependencies

The native shutdown hook remains alive while preparation is blocked, including when an administrator calls the upstream poweroff directly. A nonzero hook exit would let native shutdown continue, so watcher failure uses a blocked signal wait. Normal waiting uses inotify and process/cgroup exit events, with no sleep-based assumptions. Once native shutdown starts it cannot be cancelled.

fds-power is a static alias of fds. The CLI now directly declares the already locked libc crate for inotify, identity and signal operations. No new external crate or target package is introduced. fds-init explicitly depends on fds-cartridged, since the native hook requires its DATA checks. DHCP and its privilege-separated children now share a managed cgroup. The final native grace period is zero after managed exits and DATA verification have completed.

Regression evidence

The development archive passed rootfs rejection checks, native PID 1/service control and actual poweroff, desktop/network transitions, tooling/static-ELF checks and make check. Logs are out/logs/m10-final-*.log; desktop evidence is out/m8-vm.1c20rcpb/, native init is out/m2-vm.5ARJNL/. The final CLI image also passed native init (out/m2-vm.ysuhZ5/), all nine stage0 cases (out/m4-vm.e3SBsX/), and the ordinary-user console checks (out/m5-vm.4l796uhp/). Cartridge regression passed in out/m6-vm.p7gfwnj2/, DATA regression in out/m7-vm.82fqc9wa/, and confirmed media writes in out/m9-vm.5a58kou6/.

The development runtime tested here is out/rootfs-build.WEtGnr/, with 191 packages and 1406 AArch64 ELF files. Its rootfs SHA-256 is 9de03100b998cac2a754fc8e05acbad0bd3f45846dd637ba4c597ea3ba61f5bb. Its SYSTEM is out/system-build.dd3e74_2/system.img, SHA-256 bef3b01bc8bc68ca673aa6a0ec73892ddaa2901864eed204745749915ee34b18. The subsequent explicit init-to-cartridge package dependency was verified in the final CLI build; the development archive already includes that daemon through its base package. Runtime binaries and service behavior are identical. The CLI archive has 180 packages and 1394 AArch64 ELF files, and is 499527680 bytes.

Kernel-to-console was 1821.039788 ms versus M9's 1854.858231 ms: −33.818443 ms. The actual ARM comparison passed without a regression exception; see out/logs/m10-boot-comparison.log. This is a VM observation, not a Pi target result.

Artifact Location SHA-256
CLI rootfs out/rootfs-build.0AzReg/rootfs-aarch64.tar ebfc58171aeee6f737c2a93a0f3a318d4f02eb915edb3b5a3cf0f51848863930
CLI SYSTEM out/system-build.c7q19iil/system.img 81dc8083777b497f02a290a15eeb246465689d0deaff97d761aeb882d140b44b
FAT32 boot partition out/boot-build.42abbf_h/boot.fat 0972b5973d1fefc377ec4c800043fb8e4aa3013140f95218cdebcf38dcd22a49