Files
fds-os/docs/m10-validation.md
T
2026-09-21 22:29:23 +08:00

112 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# M10 shutdown validation
[Shutdown usage](power.md) · [Implementation ledger](implementation-status.md)
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](https://www.qemu.org/docs/master/devel/testing/blkdebug.html).
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` |