From a9e34ff905798ec1a727312de4137e48a7b8dd2f Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Thu, 8 Jun 2023 00:24:36 -0400 Subject: [PATCH 1/2] systemd stage 1 networking: Add network-pre to flush tests This isn't actually wanted by any units by default. --- nixos/tests/systemd-initrd-networkd.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nixos/tests/systemd-initrd-networkd.nix b/nixos/tests/systemd-initrd-networkd.nix index 00ecbec5613c..8376276d8f63 100644 --- a/nixos/tests/systemd-initrd-networkd.nix +++ b/nixos/tests/systemd-initrd-networkd.nix @@ -12,6 +12,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { systemd.services.check-flush = { requiredBy = ["multi-user.target"]; before = ["network-pre.target" "multi-user.target"]; + wants = ["network-pre.target"]; unitConfig.DefaultDependencies = false; serviceConfig.Type = "oneshot"; path = [ pkgs.iproute2 pkgs.iputils pkgs.gnugrep ]; From 5d6ea734a18203895360f6ea767ee47f7be22e00 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Tue, 6 Jun 2023 22:41:08 -0400 Subject: [PATCH 2/2] systemd stage 1 networking: Stop systemd-networkd on switch-root This essentially backports https://github.com/systemd/systemd/pull/27791. `systemd-networkd.service` is sent the `SIGTERM` signal, but it is not required to be stopped before `initrd-switch-root.target` is reached, despite the use of `systemctl isolate initrd-switch-root.target`. This is because when there is no ordering at all between two units, and a transaction stops one and starts the other, the two operations can happen simultaneously. This means the service could still be running when `switch-root` actually occurs. Then, stage 2 systemd will see the service still running and decide it doesn't need to add a start operation for it to its initial transaction. Finally, the service exits, but only after it's already too late. If, however, there is any ordering at all between a stopping unit and a starting unit, then the stop operation will be done first. This way, we ensure that the service is properly exited before doing `switch-root`. This is something to keep in mind going forward. There may be other services that need this treatment. These `before` and `conflicts` definitions are the correct way to ensure a unit is actually stopped before you reach initrd-switch-root --- nixos/modules/system/boot/networkd.nix | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix index 463e2b8d90b0..d88f88f9fdaf 100644 --- a/nixos/modules/system/boot/networkd.nix +++ b/nixos/modules/system/boot/networkd.nix @@ -3188,7 +3188,19 @@ let systemd.contents."/etc/systemd/networkd.conf" = renderConfig cfg.config; - systemd.services.systemd-networkd.wantedBy = [ "initrd.target" ]; + systemd.services.systemd-networkd = { + wantedBy = [ "initrd.target" ]; + # These before and conflicts lines can be removed when this PR makes it into a release: + # https://github.com/systemd/systemd/pull/27791 + before = ["initrd-switch-root.target"]; + conflicts = ["initrd-switch-root.target"]; + }; + systemd.sockets.systemd-networkd = { + wantedBy = [ "initrd.target" ]; + before = ["initrd-switch-root.target"]; + conflicts = ["initrd-switch-root.target"]; + }; + systemd.services.systemd-network-generator.wantedBy = [ "sysinit.target" ]; systemd.storePaths = [