diff --git a/man/systemd.swap.xml b/man/systemd.swap.xml index 2b65ba68f3..2dc98d3f5d 100644 --- a/man/systemd.swap.xml +++ b/man/systemd.swap.xml @@ -90,9 +90,15 @@ The following dependencies are added unless DefaultDependencies=no is set: - Swap units automatically acquire a Conflicts= and a + Local swap units automatically acquire a Conflicts= and a Before= dependency on umount.target so that they are deactivated at shutdown as well as a Before=swap.target dependency. + + Network swap units (those with in their options) automatically acquire + After= dependencies on remote-fs-pre.target and + network.target, plus After= and Wants= dependencies + on network-online.target, and a Before= dependency on + remote-fs.target instead of swap.target. @@ -124,7 +130,8 @@ With , the swap unit will not be added as a dependency for - swap.target. This means that it will not + swap.target (or remote-fs.target for network swap devices, + see below). This means that it will not be activated automatically during boot, unless it is pulled in by some other unit. The option has the opposite meaning and is the default. @@ -138,8 +145,8 @@ With , the swap unit will be only wanted, not required by - swap.target. This means that the boot - will continue even if this swap device is not activated + swap.target (or remote-fs.target for network swap + devices). This means that the boot will continue even if this swap device is not activated successfully. @@ -167,6 +174,21 @@ + + + + + Marks this swap device as requiring network access. This is useful for swap on + network block devices (e.g. iSCSI). + + Network swap units are ordered between remote-fs-pre.target and + remote-fs.target, instead of being ordered before + swap.target. They also pull in network-online.target and + are ordered after it and network.target. + + + + diff --git a/src/core/swap.c b/src/core/swap.c index 960d831c5c..cedabc430d 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -223,6 +223,7 @@ static int swap_add_device_dependencies(Swap *s) { } static int swap_add_default_dependencies(Swap *s) { + SwapParameters *p; int r; assert(s); @@ -236,13 +237,46 @@ static int swap_add_default_dependencies(Swap *s) { if (detect_container() > 0) return 0; - /* swap units generated for the swap dev links are missing the - * ordering dep against the swap target. */ - r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SWAP_TARGET, true, UNIT_DEPENDENCY_DEFAULT); - if (r < 0) - return r; + p = swap_get_parameters(s); - return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (p && fstab_test_option(p->options, "_netdev\0")) { + /* Network swap devices (those with _netdev in options) are routed through + * remote-fs.target instead of swap.target, mirroring how network mounts use + * remote-fs.target instead of local-fs.target. This avoids an ordering cycle: + * swap.target is pulled in at sysinit.target time, but network-online.target + * only comes after basic.target which is after sysinit.target. */ + r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOTE_FS_PRE_TARGET, + /* add_reference= */ true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_REMOTE_FS_TARGET, + /* add_reference= */ true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + /* Pull in and order after network-online.target, analogous to + * mount_add_default_network_dependencies() for network mounts. */ + r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_NETWORK_TARGET, + /* add_reference= */ true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, + /* add_reference= */ true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + } else { + /* swap units generated for the swap dev links are missing the + * ordering dep against the swap target. */ + r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SWAP_TARGET, + /* add_reference= */ true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + } + + return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, + /* add_reference= */ true, UNIT_DEPENDENCY_DEFAULT); } static int swap_verify(Swap *s) { diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 1bfebf3c40..572f30a1cf 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -221,6 +221,7 @@ static int add_swap( _cleanup_free_ char *name = NULL; _cleanup_fclose_ FILE *f = NULL; + bool is_network; int r; assert(what); @@ -240,11 +241,14 @@ static int add_swap( return true; } - log_debug("Found swap entry what=%s makefs=%s growfs=%s pcrfs=%s validatefs=%s noauto=%s nofail=%s", + is_network = fstab_test_option(options, "_netdev\0"); + + log_debug("Found swap entry what=%s makefs=%s growfs=%s pcrfs=%s validatefs=%s noauto=%s nofail=%s netdev=%s", what, yes_no(flags & MOUNT_MAKEFS), yes_no(flags & MOUNT_GROWFS), yes_no(flags & MOUNT_PCRFS), yes_no(flags & MOUNT_VALIDATEFS), - yes_no(flags & MOUNT_NOAUTO), yes_no(flags & MOUNT_NOFAIL)); + yes_no(flags & MOUNT_NOAUTO), yes_no(flags & MOUNT_NOFAIL), + yes_no(is_network)); r = unit_name_from_path(what, ".swap", &name); if (r < 0) @@ -285,6 +289,12 @@ static int add_swap( if (r < 0) return r; + if (is_network) { + r = generator_write_network_device_deps(arg_dest, what, /* where= */ NULL, options); + if (r < 0) + return r; + } + if (flags & MOUNT_MAKEFS) { r = generator_hook_up_mkswap(arg_dest, what); if (r < 0) @@ -300,7 +310,8 @@ static int add_swap( log_warning("%s: validating swap devices is currently unsupported.", what); if (!(flags & MOUNT_NOAUTO)) { - r = generator_add_symlink(arg_dest, SPECIAL_SWAP_TARGET, + const char *target = is_network ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_SWAP_TARGET; + r = generator_add_symlink(arg_dest, target, (flags & MOUNT_NOFAIL) ? "wants" : "requires", name); if (r < 0) return r; diff --git a/src/shared/generator.c b/src/shared/generator.c index 603e969436..fd527b3e6d 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -490,9 +490,8 @@ int generator_write_network_device_deps( assert(dir); assert(what); - assert(where); - if (fstab_is_extrinsic(where, opts)) + if (where && fstab_is_extrinsic(where, opts)) return 0; if (!fstab_test_option(opts, "_netdev\0")) diff --git a/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.container.sysroot/local-fs.target.wants/systemd-remount-fs.service b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.container.sysroot/local-fs.target.wants/systemd-remount-fs.service new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.container/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.container/initrd-usr-fs.target.requires/sysroot.mount new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.sysroot/dev-sdx1.device.d/50-netdev-dependencies.conf b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.sysroot/dev-sdx1.device.d/50-netdev-dependencies.conf new file mode 100644 index 0000000000..33d814c275 --- /dev/null +++ b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.sysroot/dev-sdx1.device.d/50-netdev-dependencies.conf @@ -0,0 +1,5 @@ +# Automatically generated by systemd-fstab-generator + +[Unit] +After=network-online.target network.target +Wants=network-online.target diff --git a/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.sysroot/dev-sdx1.swap b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.sysroot/dev-sdx1.swap new file mode 100644 index 0000000000..32f276c9e1 --- /dev/null +++ b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.sysroot/dev-sdx1.swap @@ -0,0 +1,10 @@ +# Automatically generated by systemd-fstab-generator + +[Unit] +Documentation=man:fstab(5) man:systemd-fstab-generator(8) +SourcePath=/etc/fstab +After=blockdev@dev-sdx1.target + +[Swap] +What=/dev/sdx1 +Options=_netdev diff --git a/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.sysroot/local-fs.target.wants/systemd-remount-fs.service b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.sysroot/local-fs.target.wants/systemd-remount-fs.service new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.sysroot/remote-fs.target.requires/dev-sdx1.swap b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.sysroot/remote-fs.target.requires/dev-sdx1.swap new file mode 120000 index 0000000000..00f0c5ce66 --- /dev/null +++ b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected.sysroot/remote-fs.target.requires/dev-sdx1.swap @@ -0,0 +1 @@ +../dev-sdx1.swap \ No newline at end of file diff --git a/test/test-fstab-generator/test-21-swap-netdev.fstab.expected/dev-sdx1.device.d/50-netdev-dependencies.conf b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected/dev-sdx1.device.d/50-netdev-dependencies.conf new file mode 100644 index 0000000000..33d814c275 --- /dev/null +++ b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected/dev-sdx1.device.d/50-netdev-dependencies.conf @@ -0,0 +1,5 @@ +# Automatically generated by systemd-fstab-generator + +[Unit] +After=network-online.target network.target +Wants=network-online.target diff --git a/test/test-fstab-generator/test-21-swap-netdev.fstab.expected/dev-sdx1.swap b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected/dev-sdx1.swap new file mode 100644 index 0000000000..32f276c9e1 --- /dev/null +++ b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected/dev-sdx1.swap @@ -0,0 +1,10 @@ +# Automatically generated by systemd-fstab-generator + +[Unit] +Documentation=man:fstab(5) man:systemd-fstab-generator(8) +SourcePath=/etc/fstab +After=blockdev@dev-sdx1.target + +[Swap] +What=/dev/sdx1 +Options=_netdev diff --git a/test/test-fstab-generator/test-21-swap-netdev.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected/initrd-usr-fs.target.requires/sysroot.mount new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/test-fstab-generator/test-21-swap-netdev.fstab.expected/remote-fs.target.requires/dev-sdx1.swap b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected/remote-fs.target.requires/dev-sdx1.swap new file mode 120000 index 0000000000..00f0c5ce66 --- /dev/null +++ b/test/test-fstab-generator/test-21-swap-netdev.fstab.expected/remote-fs.target.requires/dev-sdx1.swap @@ -0,0 +1 @@ +../dev-sdx1.swap \ No newline at end of file diff --git a/test/test-fstab-generator/test-21-swap-netdev.fstab.input b/test/test-fstab-generator/test-21-swap-netdev.fstab.input new file mode 100644 index 0000000000..5f719a4202 --- /dev/null +++ b/test/test-fstab-generator/test-21-swap-netdev.fstab.input @@ -0,0 +1 @@ +/dev/sdx1 none swap _netdev 0 0