I can’t seem to get that workaround working for me, either. I tried removing the old swap file, creating a new one using dd, fixing the permissions, and restarting the service, but I’m still getting swapon failed: Invalid argument, no matter what. Furthermore, in journalctl -xe I see kernel: swapon: swapfile has holes.
Forgot to mention, the size you use for the dd command needs to exactly match the size set in the module, otherwise the module will call fallocate again:
For those of you who are still having this problem, the following has worked well for me:
The proper way to create a Swap file on BTRFS is Btrfs - ArchWiki, so I set up a oneshot systemd service to create this file for me that is wanted by the NixOS swap-*.service defined in my hardware-configuration.nix file.
This will create the non-compressed, CoW disabled file in my /swap BTRFS subvolume. Then I leave the allocation and enabling of the swap file to NixOS in hardware-configuration.nix
fileSystems."/swap" = {
device = "/dev/disk/by-uuid/545353bc-238b-4a5b-bb48-94832272e0b2";
fsType = "btrfs";
options = [ "subvol=swap" "compress=lzo" "noatime" ]; # Note these options effect the entire BTRFS filesystem and not just this volume, with the exception of `"subvol=swap"`, the other options are repeated in my other `fileSystem` mounts
};
swapDevices = [{
device = "/swap/swapfile";
size = (1024 * 16) + (1024 * 2); # RAM size + 2 GB
}];
As you can see, my nixops deploy succeeds and upon verification the file is enabled and allocated according to my definition.
Thanks for this example! Worked for me with some small tweaks. My goal was enabling hibernation with BTRFS and LUKS.
First needed to run sudo btrfs subvolume create /swap. Then made the following tweaks:
Seems ${pkgs.btrfs-progs}/bin/btrfs property set /swap/swapfile compression none is no longer needed, and in fact it errored out doing this, so I just deleted the line
Skipped adding fileSystems."/swap"
Noticed the create-swapfile service fails once the swap file exists, so added a check into the script:
swapfile="/swap/swapfile"
if [[ -f "$swapfile" ]]; then
echo "Swap file $swapfile already exists, taking no action"
else
echo "Setting up swap file $swapfile"
${pkgs.coreutils}/bin/truncate -s 0 "$swapfile"
${pkgs.e2fsprogs}/bin/chattr +C "$swapfile"
fi
To hibernate to the file, I followed the Arch wiki for calculating the resume_offset. I created a script to automate the end value.
Finally I added the following to my hardware-configuration.nix: boot.kernelParams = ["resume_offset=95450174"]; boot.resumeDevice = "/dev/disk/by-uuid/${rootUUID}";
Final note, this does not seem to work with boot.initrd.systemd.enable = true;.