From 870fa77ff6eeba7eff8596869b50c4c475033c03 Mon Sep 17 00:00:00 2001 From: hyperfekt Date: Wed, 2 Dec 2020 00:52:54 +0100 Subject: [PATCH 1/2] nixos/filesystems: mount persistent storage to /sys/fs/pstore --- nixos/modules/tasks/filesystems.nix | 34 +++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index e468cb88003..2aeb8598ada 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -272,10 +272,10 @@ in wants = [ "local-fs.target" "remote-fs.target" ]; }; - # Emit systemd services to format requested filesystems. systemd.services = - let + # Emit systemd services to format requested filesystems. + let formatDevice = fs: let mountPoint' = "${escapeSystemdPath fs.mountPoint}.mount"; @@ -302,8 +302,34 @@ in unitConfig.DefaultDependencies = false; # needed to prevent a cycle serviceConfig.Type = "oneshot"; }; - - in listToAttrs (map formatDevice (filter (fs: fs.autoFormat) fileSystems)); + in listToAttrs (map formatDevice (filter (fs: fs.autoFormat) fileSystems)) // { + # Mount /sys/fs/pstore for evacuating panic logs and crashdumps from persistent storage onto the disk using systemd-pstore. + # This cannot be done with the other special filesystems because the pstore module (which creates the mount point) is not loaded then. + # Since the pstore filesystem is usually empty right after mounting because the backend isn't registered yet, and a path unit cannot detect files inside of it, the same service waits for that to happen. systemd's restart mechanism can't be used here because the first failure also fails all dependent units. + "mount-pstore" = { + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.utillinux}/bin/mount -t pstore -o nosuid,noexec,nodev pstore /sys/fs/pstore"; + ExecStartPost = pkgs.writeShellScript "wait-for-pstore.sh" '' + set -eu + TRIES=0 + while [ $TRIES -lt 20 ] && [ "$(cat /sys/module/pstore/parameters/backend)" = "(null)" ]; do + sleep 0.1 + TRIES=$((TRIES+1)) + done + ''; + RemainAfterExit = true; + }; + unitConfig = { + ConditionVirtualization = "!container"; + DefaultDependencies = false; # needed to prevent a cycle + }; + after = [ "modprobe@pstore.service" ]; + requires = [ "modprobe@pstore.service" ]; + before = [ "systemd-pstore.service" ]; + wantedBy = [ "systemd-pstore.service" ]; + }; + }; systemd.tmpfiles.rules = [ "d /run/keys 0750 root ${toString config.ids.gids.keys}" From 3e3e763a075cea09e6db7a4ec51aa0e90435f2fe Mon Sep 17 00:00:00 2001 From: hyperfekt Date: Wed, 2 Dec 2020 00:54:35 +0100 Subject: [PATCH 2/2] nixos/systemd: enable systemd-pstore.service As described in issue #81138, the Install section of upstream units is currently ignored, so we make it part of the sysinit.target manually. --- nixos/doc/manual/release-notes/rl-2105.xml | 6 ++++++ nixos/modules/profiles/installation-device.nix | 8 ++++++++ nixos/modules/system/boot/systemd.nix | 2 ++ 3 files changed, 16 insertions(+) diff --git a/nixos/doc/manual/release-notes/rl-2105.xml b/nixos/doc/manual/release-notes/rl-2105.xml index 924fe7ae038..d767b8ba74b 100644 --- a/nixos/doc/manual/release-notes/rl-2105.xml +++ b/nixos/doc/manual/release-notes/rl-2105.xml @@ -1035,6 +1035,12 @@ environment.systemPackages = [ + + + The newly enabled systemd-pstore.service now automatically evacuates crashdumps and panic logs from the persistent storage to /var/lib/systemd/pstore. + This prevents NVRAM from filling up, which ensures the latest diagnostic data is always stored and alleviates problems with writing new boot configurations. + + diff --git a/nixos/modules/profiles/installation-device.nix b/nixos/modules/profiles/installation-device.nix index 7dc493fb495..8e3aa20daa6 100644 --- a/nixos/modules/profiles/installation-device.nix +++ b/nixos/modules/profiles/installation-device.nix @@ -99,5 +99,13 @@ with lib; # because we have the firewall enabled. This makes installs from the # console less cumbersome if the machine has a public IP. networking.firewall.logRefusedConnections = mkDefault false; + + # Prevent installation media from evacuating persistent storage, as their + # var directory is not persistent and it would thus result in deletion of + # those entries. + environment.etc."systemd/pstore.conf".text = '' + [PStore] + Unlink=no + ''; }; } diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index d4ae4c93468..6be7b7e6846 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -90,6 +90,7 @@ let "systemd-fsck@.service" "systemd-fsck-root.service" "systemd-remount-fs.service" + "systemd-pstore.service" "local-fs.target" "local-fs-pre.target" "remote-fs.target" @@ -1183,6 +1184,7 @@ in systemd.targets.remote-fs.unitConfig.X-StopOnReconfiguration = true; systemd.targets.network-online.wantedBy = [ "multi-user.target" ]; systemd.services.systemd-importd.environment = proxy_env; + systemd.services.systemd-pstore.wantedBy = [ "sysinit.target" ]; # see #81138 # Don't bother with certain units in containers. systemd.services.systemd-remount-fs.unitConfig.ConditionVirtualization = "!container";