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

133 lines
6.4 KiB
Markdown

# Shutdown and reboot
[Documentation index](README.md) · [DATA usage](data.md) · [Media tools](media-tools.md)
M10 software acceptance passed; see the [validation report](m10-validation.md).
Physical timing and durability targets remain unmeasured. Rebuild the rootfs to
obtain these commands; images built before M10 do not contain them.
## Normal use
At the ordinary FDS console:
```sh
fds poweroff
fds reboot
```
Use one command for the action you want. `fds-power poweroff` and `fds-power
reboot` are equivalent static aliases. No root password or setuid executable is
needed: the root cartridge daemon authenticates the local FDS user and performs
the controlled operation.
Preparation freezes new cartridge operations, stops the desktop, stops managed
PROGRAM/DATA jobs and their descendants, then stops networking and all DHCP
children. It flushes DATA through the filesystem descriptor retained since
activation, changes the filesystem to read-only, checks writeback again, and
unmounts it normally. Other cartridges are unmounted next. Only after those
steps succeed does native s6 stop remaining services and request kernel halt or
reboot. Dasung remains part of the base service set until that final service stop.
The read-only transition prevents new writes while the error-tracking descriptor
is closed for unmount. An open writer blocks that transition. A working
directory or unexpected additional mount can block unmount. No lazy unmount is
used to turn a busy or faulty cartridge into a successful shutdown.
## If shutdown is blocked
The machine stays running and the command reports the cause. Inspect it with:
```sh
fds power status
fds --json power status
```
The JSON response includes the current phase, requested action, error, whether
native shutdown has begun, and actual `CLOCK_BOOTTIME` timestamps for preparation
steps. It is a software diagnostic, not a physical power-off measurement.
Common cases:
| Reported problem | What to do |
| --- | --- |
| Active media operation | Let an existing write finish, or use `fds burn cancel OPERATION_ID`. A preview awaiting confirmation must be cancelled. New confirmations are refused while shutdown is frozen. Then retry shutdown. |
| Busy DATA filesystem | Close files and programs that were started outside FDS management. Leave `/data` in every shell with `cd /`. Remove any extra mounts you deliberately created. Then retry shutdown. |
| DATA I/O error or interrupted session | Do not interpret this as SAFE. Inspect the read-only data and recover/check the cartridge in a maintenance environment before writable use. Restarting the daemon does not clear this fault. |
| Service transition failure | Inspect the corresponding volatile service logs under `/run/log`, resolve the failure, and retry. |
If native shutdown has **not** begun, you can abandon preparation:
```sh
fds power resume
```
This enables new cartridge operations again. It does not restart stopped jobs.
Start the desktop or network explicitly when needed, using `fds profile activate
windowmaker` and `fds network on`. DATA faults remain quarantined.
If native shutdown has already begun, it cannot be cancelled. Its guard remains
alive while preparation is blocked. Resolve the cause, leave busy directories,
then retry `fds poweroff` to complete preparation; the original native action
continues. This also protects direct administrative use of the native `poweroff`
or `reboot` commands. The final native hook never treats an unsuccessful
preparation command as permission to kill processes and power down.
Flushing real storage may take time. A client timeout is an error, never proof
that a filesystem was unmounted or a request completed. There is no automatic
force-poweroff path after a timeout.
## DATA recovery records
Before enabling writable DATA, FDS creates a root-owned session record under
`/run/fds/data-sessions`. Successful sync and unmount clear it. A daemon crash
can lose the original descriptor's writeback error history; a remaining record
therefore quarantines the same kernel insertion even if a later flush appears
successful. A known I/O fault is also recorded there.
The record survives daemon restarts during this boot. It is tied to the kernel
insertion identity and does not pretend to survive complete power loss or a new
insertion. Filesystem recovery and physical durability still require separate
acceptance. Shutdown preparation itself is recorded under `/run/fds/power`, so
restarting the daemon does not silently unfreeze a blocked shutdown.
## Build and virtual tests
After the [boot-image prerequisites](boot.md), run on the build host:
```sh
make rootfs PROFILE=development
make rootfs-test
make media-image-test
make power-test
make data-test
make desktop-test
```
The development profile supplies Xvfb for the graphical shutdown case. The
tests use private ARM virtual machines and disposable image files, with no
physical disks or USB devices passed through. They exercise native halt/reboot,
busy refusal, explicit resume, active-write protection, daemon crashes, and
independent filesystem/payload checks, plus an attached-device writeback EIO
that must survive daemon restarts. M11 extends media-writer fault injection and
twelve-device stress. Physical Pi timing, power rails, battery and
flash-controller behavior remain deferred.
## Dependencies and native init behavior
No new package or external Rust crate is introduced. `fds-init` explicitly
depends on `fds-cartridged` because native shutdown requires its DATA checks. The CLI now declares the
already-locked `libc` crate directly for its native shutdown guard's identity,
inotify and signal-wait syscalls. DHCP children use the existing cgroup v2
controller and native FDS helpers. `fds-power` is another static copy of `fds`,
with behavior selected by its executable name.
Native s6 still owns shutdown and PID 1. Its configurable final grace period is
set to zero after FDS has verified DATA and the service manager has waited for
managed service exits. Process groups use real exit events and bounded TERM/KILL
deadlines, rather than sleeping before assuming a process has stopped.
References: [s6 shutdown](https://skarnet.org/software/s6-linux-init/s6-linux-init-shutdown.html),
[native init configuration](https://skarnet.org/software/s6-linux-init/s6-linux-init-maker.html),
[Linux remount behavior](https://man7.org/linux/man-pages/man2/mount.2.html), and
[filesystem error reporting](https://man7.org/linux/man-pages/man2/syncfs.2.html).