m/n/core: add pstore handling
Adds a one-shot runnable which dumps all kmsg dumps to the system log
and then clears the pstore. This makes sure that there is always space
for new pstore entries and gives administrators the option of reading
crash logs without booting another operating system. It also helps some
broken EFI firmware to not fail to boot.
Change-Id: Icbf30c0a0898e0e660910a80637d544f022a97cd
Reviewed-on: https://review.monogon.dev/c/monogon/+/770
Reviewed-by: Sergiusz Bazanski <serge@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/node/core/pstore.go b/metropolis/node/core/pstore.go
new file mode 100644
index 0000000..01f6cfd
--- /dev/null
+++ b/metropolis/node/core/pstore.go
@@ -0,0 +1,35 @@
+package main
+
+import (
+ "context"
+
+ "source.monogon.dev/metropolis/pkg/pstore"
+ "source.monogon.dev/metropolis/pkg/supervisor"
+)
+
+// dumpAndCleanPstore dumps all files accumulated in the pstore into the log
+// and clears them from the pstore. This allows looking at these logs and also
+// keeps the pstore from overflowing the generally limited storage it has.
+func dumpAndCleanPstore(ctx context.Context) error {
+ logger := supervisor.Logger(ctx)
+ // Retrying this is extremely unlikely to result in any change and is most
+ // likely just going to generate large amounts of useless logs obscuring
+ // errors.
+ supervisor.Signal(ctx, supervisor.SignalDone)
+ dumps, err := pstore.GetKmsgDumps()
+ if err != nil {
+ logger.Errorf("Failed to recover logs from pstore: %v", err)
+ return nil
+ }
+ for _, dump := range dumps {
+ logger.Errorf("Recovered log from %v at %v. Reconstructed log follows.", dump.Reason, dump.OccurredAt)
+ for _, line := range dump.Lines {
+ logger.Warning(line)
+ }
+ }
+ cleanErr := pstore.ClearAll()
+ if cleanErr != nil {
+ logger.Errorf("Failed to clear pstore: %v", err)
+ }
+ return nil
+}