From 1541311f06a0fd148ace46bb0adaa3f968b36d1e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 7 Jan 2013 16:03:35 +0100 Subject: [PATCH] switch-to-configuration: Stop some target units to ensure proper dependency ordering This is currently only done for network-interfaces.target, but it should propably be done for most targets. --- .../activation/switch-to-configuration.pl | 18 +++++++++++++++++- modules/tasks/network-interfaces.nix | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/modules/system/activation/switch-to-configuration.pl b/modules/system/activation/switch-to-configuration.pl index 28ccc158f72..44cd261cf98 100644 --- a/modules/system/activation/switch-to-configuration.pl +++ b/modules/system/activation/switch-to-configuration.pl @@ -117,6 +117,8 @@ while (my ($unit, $state) = each %{$activePrev}) { } elsif ($unit =~ /\.target$/) { + my $unitInfo = parseUnit($newUnitFile); + # Cause all active target units to be restarted below. # This should start most changed units we stop here as # well as any new dependencies (including new mounts and @@ -124,11 +126,25 @@ while (my ($unit, $state) = each %{$activePrev}) { # active after the system has resumed, which probably # should not be the case. Just ignore it. if ($unit ne "suspend.target" && $unit ne "hibernate.target") { - my $unitInfo = parseUnit($newUnitFile); unless (boolIsTrue($unitInfo->{'RefuseManualStart'} // "false")) { write_file($startListFile, { append => 1 }, "$unit\n"); } } + + # Stop targets that have X-StopOnReconfiguration set. + # This is necessary to respect dependency orderings + # involving targets: if unit X starts after target Y and + # target Y starts after unit Z, then if X and Z have both + # changed, then X should be restarted after Z. However, + # if target Y is in the "active" state, X and Z will be + # restarted at the same time because X's dependency on Y + # is already satisfied. Thus, we need to stop Y first. + # Stopping a target generally has no effect on other units + # (unless there is a PartOf dependency), so this is just a + # bookkeeping thing to get systemd to do the right thing. + if (boolIsTrue($unitInfo->{'X-StopOnReconfiguration'} // "false")) { + push @unitsToStop, $unit; + } } elsif (abs_path($prevUnitFile) ne abs_path($newUnitFile)) { diff --git a/modules/tasks/network-interfaces.nix b/modules/tasks/network-interfaces.nix index 82f4d3da4f1..a002e2b68b2 100644 --- a/modules/tasks/network-interfaces.nix +++ b/modules/tasks/network-interfaces.nix @@ -255,6 +255,7 @@ in boot.systemd.targets."network-interfaces" = { description = "All Network Interfaces"; wantedBy = [ "network.target" ]; + unitConfig.X-StopOnReconfiguration = true; }; boot.systemd.services =