From 6d50e67bd2af7bbab1fd336b40106da5c15396bf Mon Sep 17 00:00:00 2001 From: Nikos Dragazis Date: Mon, 2 Feb 2026 20:34:32 +0200 Subject: [PATCH] scylla_swap_setup: Remove Before=swap.target dependency from swap unit When a Scylla node starts, the scylla-image-setup.service invokes the `scylla_swap_setup` script to provision swap. This script allocates a swap file and creates a swap systemd unit to delegate control to systemd. By default, systemd injects a Before=swap.target dependency into every swap unit, allowing other services to use swap.target to wait for swap to be enabled. On Azure, this doesn't work so well because we store the swap file on the ephemeral disk [1] which has network dependencies (`_netdev` mount option, configured by cloud-init [2]). This makes the swap.target indirectly depend on the network, leading to dependency cycles such as: swap.target -> mnt-swapfile.swap -> mnt.mount -> network-online.target -> network.target -> systemd-resolved.service -> tmp.mount -> swap.target This patch breaks the cycle by removing the swap unit from swap.target using DefaultDependencies=no. The swap unit will still be activated via WantedBy=multi-user.target, just not during early boot. Although this problem is specific to Azure, this patch applies the fix to all clouds to keep the code simple. Fixes #26519. Fixes SCYLLADB-1257 [1] https://github.com/scylladb/scylla-machine-image/pull/426 [2] https://github.com/canonical/cloud-init/pull/1213#issuecomment-1026065501 Signed-off-by: Nikos Dragazis Closes scylladb/scylladb#28504 --- dist/common/scripts/scylla_swap_setup | 28 ++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/dist/common/scripts/scylla_swap_setup b/dist/common/scripts/scylla_swap_setup index 4ffdae56d0..b8c5ab202d 100755 --- a/dist/common/scripts/scylla_swap_setup +++ b/dist/common/scripts/scylla_swap_setup @@ -9,6 +9,7 @@ import os import sys +import shlex import argparse import psutil from pathlib import Path @@ -103,16 +104,41 @@ if __name__ == '__main__': run('dd if=/dev/zero of={} bs=1M count={}'.format(swapfile, swapsize_mb), shell=True, check=True) swapfile.chmod(0o600) run('mkswap -f {}'.format(swapfile), shell=True, check=True) + + mount_point = find_mount_point(swap_directory) + mount_unit = out(f'systemd-escape -p --suffix=mount {shlex.quote(str(mount_point))}') + + # Add DefaultDependencies=no to the swap unit to avoid getting the default + # Before=swap.target dependency. We apply this to all clouds, but the + # requirement came from Azure: + # + # On Azure, the swap directory is on the Azure ephemeral disk (mounted on /mnt). + # However, cloud-init makes this mount (i.e., the mnt.mount unit) depend on + # the network (After=network-online.target). By extension, this means that + # the swap unit depends on the network. If we didn't use DefaultDependencies=no, + # then the swap unit would be part of the swap.target which other services + # assume to be a local boot target, so we would end up with dependency cycles + # such as: + # + # swap.target -> mnt-swapfile.swap -> mnt.mount -> network-online.target -> network.target -> systemd-resolved.service -> tmp.mount -> swap.target + # + # By removing the automatic Before=swap.target, the swap unit is no longer + # part of swap.target, avoiding such cycles. The swap will still be + # activated via WantedBy=multi-user.target. unit_data = ''' [Unit] Description=swapfile +DefaultDependencies=no +After={} +Conflicts=umount.target +Before=umount.target [Swap] What={} [Install] WantedBy=multi-user.target -'''[1:-1].format(swapfile) +'''[1:-1].format(mount_unit, swapfile) with swapunit.open('w') as f: f.write(unit_data) systemd_unit.reload()