2.6 Boot Modes
peinit boots in one of three modes, forming an escalation path from normal operation to last-resort maintenance.
Full boot ---+-- success ----------------> counter reset, operational
|
+-- cycle w/ Critical ------> Safe mode (no reboot)
|
+-- conflict w/ Critical ---> Safe mode (no reboot)
|
+-- Critical failure -------> sync + reboot --+
|
Safe boot ---+-- success ----------------> counter reset, |
| operational (reduced) |
+-- Critical failure -------> sync + reboot --+
|
counter increments <----------+
|
counter >= N ---------> Recovery mode
Phase 1 failure ------> Recovery mode
2.6.1 Full mode #
The default. Every boot-triggered service starts in dependency order, as §2.5 describes.
2.6.2 Safe mode #
Safe mode starts a reduced set. Eligibility is a filter within the
boot-triggered set, not a replacement for it: a service with no boot
trigger does not auto-start in Safe mode whatever its SafeMode or
ErrorControl says, and remains demand-only.
Within the
boot-triggered set, two categories are eligible:
- Critical services (
ErrorControl=Critical) start. If one fails, the ordinary Critical failure path applies — restart budget, reboot, counter increment, eventually recovery. SafeMode=1services are attempted best-effort. If one fails, Safe mode continues without it.
ErrorControl=Critical implies SafeMode, so a Critical service does
not have to declare both.
2.6.2.1 What caused the downgrade #
The rebuild discards the Full-mode graph, so a service that forced Safe
mode and is then excluded from the rebuilt graph is never entered into
the blocked set and never marked Failed. That is deliberate: Safe mode
was never going to start it, and a Failed state would say something
about its own health that is not true. status should keep meaning
"this service is broken".
A service that survives into the rebuilt graph gets no such protection.
Two Critical services that require each other are both eligible in
Safe mode, so the rebuild contains the same cycle and blocks them both,
exactly as it would anywhere else — and there is no order that could
have started either.
The reason is therefore recorded at boot level rather than per
service. Every finding that forced the downgrade — each critical cycle,
each critical boot conflict — is written to the console and emitted as a
peinit.boot.downgraded KMES event naming the services involved, an
essential type the emission policy cannot switch off.
All of them are reported, not just the first. A machine can be downgraded by a cycle and a conflict at once, and an operator who fixed only the one they were shown would reboot straight back into Safe mode.
They stay available for the rest of the boot: the control socket's
boot command reports the mode, why, and every finding (§10.8).
peinit rebuilds the dependency graph from scratch using only the eligible services. Dependencies on excluded services are dropped: if A depends on non-Critical B and B is excluded, A's dependency on B does not exist in the Safe mode graph. This is what makes Safe mode useful — it is a graph in which the broken parts of the configuration are simply not present, rather than a graph in which they are present and failing.
A successful Safe boot resets the boot attempt counter.
2.6.2.2 Entry #
- A cycle involving a Critical service at boot. Graph validation detects it and peinit downgrades in place, without rebooting — the cycle is a configuration error, and rebooting would find it again.
- An unresolvable conflict involving a Critical service at boot. Same reasoning.
peios.safemode=1on the kernel command line.
Safe mode is not entered because a Critical service crashed at runtime. That follows the ordinary path: restart budget, reboot, counter increment, recovery.
2.6.3 Console output #
peios.quiet=N bounds what peinit writes to the console:
The two rules are independent, and an error is never less visible at 2
than at 1. A terminal is matched by device rather than by path, since
/dev/console and /dev/ttyS<n> can name the same device
; where the device
cannot be determined, peinit treats the terminal as free and writes to
it. Guessing wrong
in that direction costs a scrambled line, which is recoverable;
guessing wrong the other way costs the operator their console output at
the moment the machine is least able to explain itself.
Suppressed messages are discarded rather than buffered.
The autorun step (§2.3) bypasses the policy: a script that ran that early and went wrong is worth interrupting a login prompt for.
2.6.4 Kernel command line #
A malformed value is ignored in favour of the default rather than failing the boot. Nothing exists this early to report a diagnostic to.