mirror of
https://github.com/kevinveenbirkenbach/create-linux-swapfile.git
synced 2026-10-26 07:52:14 +00:00
fix(btrfs): allocate the swapfile with fallocate instead of dd
On a btrfs root the swapfile was written with dd from /dev/zero, so a swapfile the size of the RAM cost tens of GiB of writes and stalled every other writer on the filesystem. A caller that bounds the run, such as an async Ansible task, killed dd halfway, and the next run found the wrong size and started over. btrfs accepts a preallocated NOCOW swapfile and the swap directory already carries +C, so every filesystem now allocates with fallocate. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
43cdce5fba
commit
91e1eff8a6
4 files changed
+19
-34
No files matched your search
+1
-1
@@ -21,7 +21,7 @@ case "${SWAPFORGE}" in
|
||||
esac
|
||||
echo "ok: resolved from the installed package, not the source tree"
|
||||
|
||||
for binary in findmnt swapoff chmod mkswap swapon fallocate chattr btrfs dd; do
|
||||
for binary in findmnt swapoff fallocate chmod mkswap swapon chattr btrfs; do
|
||||
command -v "${binary}" >/dev/null || fail "${binary} is missing from the image"
|
||||
done
|
||||
echo "ok: every declared binary is present"
|
||||
|
||||
@@ -7,7 +7,6 @@ from swap_forge.core import (
|
||||
BTRFS_BINARIES,
|
||||
BTRFS_SWAP_PATH,
|
||||
DEFAULT_SWAP_PATH,
|
||||
NON_BTRFS_BINARIES,
|
||||
REQUIRED_BINARIES,
|
||||
MissingBinaryError,
|
||||
create_swap,
|
||||
@@ -22,28 +21,24 @@ from swap_forge.core import (
|
||||
|
||||
class TestRequiredBinaries(unittest.TestCase):
|
||||
def test_declares_every_external_command_the_package_calls(self):
|
||||
declared = (
|
||||
set(REQUIRED_BINARIES) | set(BTRFS_BINARIES) | set(NON_BTRFS_BINARIES)
|
||||
)
|
||||
declared = set(REQUIRED_BINARIES) | set(BTRFS_BINARIES)
|
||||
|
||||
self.assertEqual(
|
||||
declared,
|
||||
{
|
||||
"findmnt",
|
||||
"swapoff",
|
||||
"fallocate",
|
||||
"chmod",
|
||||
"mkswap",
|
||||
"swapon",
|
||||
"chattr",
|
||||
"btrfs",
|
||||
"dd",
|
||||
"fallocate",
|
||||
},
|
||||
)
|
||||
|
||||
def test_filesystem_specific_binaries_are_not_declared_as_always_required(self):
|
||||
self.assertFalse(set(REQUIRED_BINARIES) & set(BTRFS_BINARIES))
|
||||
self.assertFalse(set(REQUIRED_BINARIES) & set(NON_BTRFS_BINARIES))
|
||||
|
||||
def test_missing_binary_is_reported_with_its_name(self):
|
||||
with mock.patch("swap_forge.core.subprocess.run") as subprocess_run:
|
||||
@@ -153,7 +148,7 @@ class TestCreateSwap(unittest.TestCase):
|
||||
self.assertEqual(commands, ["fallocate", "chmod", "mkswap", "swapon"])
|
||||
self.assertEqual(fstab.read_text(), f"{swapfile} none swap sw 0 0\n")
|
||||
|
||||
def test_btrfs_disables_copy_on_write_and_uses_dd(self):
|
||||
def test_btrfs_disables_copy_on_write_before_fallocate(self):
|
||||
with tempfile.TemporaryDirectory() as base:
|
||||
swapfile = Path(base) / "swap" / "swapfile"
|
||||
fstab = Path(base) / "fstab"
|
||||
@@ -164,7 +159,11 @@ class TestCreateSwap(unittest.TestCase):
|
||||
|
||||
commands = [call.args[0][0] for call in run.call_args_list]
|
||||
self.assertEqual(
|
||||
commands, ["chattr", "btrfs", "dd", "chmod", "mkswap", "swapon"]
|
||||
commands, ["chattr", "btrfs", "fallocate", "chmod", "mkswap", "swapon"]
|
||||
)
|
||||
self.assertEqual(
|
||||
run.call_args_list[2].args[0],
|
||||
["fallocate", "-l", "1024M", str(swapfile)],
|
||||
)
|
||||
self.assertTrue(swapfile.parent.is_dir())
|
||||
|
||||
|
||||
Reference in new issue
Block a user