From f19065c283f69e44caeddb20fab9051ac52a31ec Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Sun, 22 Sep 2013 21:04:54 +0200 Subject: [PATCH] Fix broken systemd shutdown services The services systemd-random-seed-save.service and systemd-update-utmp-shutdown.service from systemd 203 don't work, because they have a RequiresMountFor dependency on /var/lib and /var/log. Such a dependency produces a cycle, causing systemd to drop those services: Fixing conflicting jobs by deleting job poweroff.target/stop Deleting job systemd-poweroff.service/stop as dependency of job poweroff.target/stop Deleting job umount.target/stop as dependency of job systemd-poweroff.service/stop Deleting job -.mount/start as dependency of job umount.target/stop Deleting job systemd-random-seed-save.service/start as dependency of job -.mount/start Deleting job systemd-update-utmp-shutdown.service/start as dependency of job -.mount/start Dropping the RequiresMountFor doesn't work either, because then /var/... may have meen unmounted or remounted read-only. Upstream systemd fixes this by doing the actual work from an ExecStop action in an already-running service than conflicts with shutdown.target. So I backported that here. The main consequence is that wtmp shutdown records now get written properly. The main lesson: shutdown.target is useless for pulling in services during shutdown if they need to write anywhere. --- modules/system/boot/systemd-unit-options.nix | 9 ++++ modules/system/boot/systemd.nix | 49 ++++++++++++++------ 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/modules/system/boot/systemd-unit-options.nix b/modules/system/boot/systemd-unit-options.nix index e3542ce9225a..be3fbd556741 100644 --- a/modules/system/boot/systemd-unit-options.nix +++ b/modules/system/boot/systemd-unit-options.nix @@ -76,6 +76,15 @@ rec { ''; }; + conflicts = mkOption { + default = []; + types = types.listOf types.string; + description = '' + If the specified units are started, then this unit is stopped + and vice versa. + ''; + }; + requiredBy = mkOption { default = []; types = types.listOf types.string; diff --git a/modules/system/boot/systemd.nix b/modules/system/boot/systemd.nix index da34d435a3f2..21b3e5e80a03 100644 --- a/modules/system/boot/systemd.nix +++ b/modules/system/boot/systemd.nix @@ -73,13 +73,6 @@ let "systemd-initctl.socket" "systemd-initctl.service" - # Random seed. - "systemd-random-seed-load.service" - "systemd-random-seed-save.service" - - # Utmp maintenance. - "systemd-update-utmp-shutdown.service" - # Kernel module loading. #"systemd-modules-load.service" @@ -158,6 +151,7 @@ let Before = concatStringsSep " " config.before; BindsTo = concatStringsSep " " config.bindsTo; PartOf = concatStringsSep " " config.partOf; + Conflicts = concatStringsSep " " config.conflicts; "X-Restart-Triggers" = toString config.restartTriggers; } // optionalAttrs (config.description != "") { Description = config.description; @@ -600,13 +594,42 @@ in users.extraGroups.systemd-journal.gid = config.ids.gids.systemd-journal; - # FIXME: This should no longer be needed with systemd >= 204. - systemd.services."systemd-update-utmp-reboot.service" = - { description = "Update UTMP about System Reboot"; + # FIXME: These are borrowed from upstream systemd. + systemd.services."systemd-update-utmp" = + { description = "Update UTMP about System Reboot/Shutdown"; wantedBy = [ "sysinit.target" ]; - unitConfig.DefaultDependencies = false; - serviceConfig.Type = "oneshot"; - serviceConfig.ExecStart = "${systemd}/lib/systemd/systemd-update-utmp reboot"; + after = [ "systemd-remount-fs.service" ]; + before = [ "sysinit.target" "shutdown.target" ]; + conflicts = [ "shutdown.target" ]; + unitConfig = { + DefaultDependencies = false; + RequiresMountsFor = "/var/log"; + }; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${systemd}/lib/systemd/systemd-update-utmp reboot"; + ExecStop = "${systemd}/lib/systemd/systemd-update-utmp shutdown"; + }; + restartIfChanged = false; + }; + + systemd.services."systemd-random-seed" = + { description = "Load/Save Random Seed"; + wantedBy = [ "sysinit.target" "multi-user.target" ]; + after = [ "systemd-remount-fs.service" ]; + before = [ "sysinit.target" "shutdown.target" ]; + conflicts = [ "shutdown.target" ]; + unitConfig = { + DefaultDependencies = false; + RequiresMountsFor = "/var/lib"; + }; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${systemd}/lib/systemd/systemd-random-seed load"; + ExecStop = "${systemd}/lib/systemd/systemd-random-seed save"; + }; }; };