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