Difficulty: ★★★☆☆
- Create and activate a Swap Device
# Set the root device:
export fs_uuid=$(findmnt / -o UUID -n) && echo ${fs_uuid}
# Temporarily mount your btrfs filesystem to a folder
sudo mount -m -U $fs_uuid /mnt/system-${fs_uuid}
# create a subvolume
sudo btrfs subvolume create /mnt/system-${fs_uuid}/@swap
# unmount the FSTREE
sudo umount /mnt/system-${fs_uuid}
# mount @swap to the root filesystem.
sudo mount -m -U ${fs_uuid} -o subvol=@swap,nodatacow /swap
- Create a swapfile
# Calculate the size: RAM * 1.6
export swp_size=$(echo "$(grep "MemTotal" /proc/meminfo | tr -d "[:blank:],[:alpha:],:") * 1.6 / 1000" | bc ) && echo ${swp_size}m
# Create the swap file
sudo btrfs filesystem mkswapfile --size ${swp_size}m --uuid clear /swap/swapfile
- Add 2 entries and enable the swapfile in
/etc/fstab
# unmount @swap
sudo umount /swap
# create the @swap entry
echo -e "UUID=$fs_uuid\t/swap\tbtrfs\tsubvol=@swap,nodatacow,noatime,nospace_cache\t0\t0" | sudo tee -a /etc/fstab
# create the swap file entry
echo -e "/swap/swapfile\tnone\tswap\tdefaults\t0\t0" | sudo tee -a /etc/fstab
# Reload daemons
sudo systemctl daemon-reload
# mount @swap
sudo mount /swap
# mount all available swap devices
sudo swapon -a
# Check which one is activated
swapon -s
If you use the systemd-init, then that is all you need. Do a reboot.
The following is only needed for busybox-init. See: mkinitcpio - ArchWiki
Enable Hibernation
# Get the UUID of the swap file
export swp_uuid=$(findmnt -no UUID -T /swap/swapfile) && echo $swp_uuid
# Get the swap file offset
export swp_offset=$(sudo btrfs inspect-internal map-swapfile /swap/swapfile | awk '/Resume offset:/ { print $3 }') && echo $swp_offset
# Make sure /etc/default/grub.d exists:
sudo mkdir -pv /etc/default/grub.d/
# Add the kernel parameter to grub
echo -e "GRUB_CMDLINE_LINUX_DEFAULT+=\" resume=UUID=$swp_uuid resume_offset=$swp_offset \"" | sudo tee -a /etc/default/grub.d/00-overwrite.cfg
# Add the resume hook
# Or use "HOOKS+=\" resume \"" if it is string.
echo -e "HOOKS+=( resume )" | sudo tee -a /etc/mkinitcpio.conf
# Recreate the initramfs
sudo mkinitcpio -P
# Recreate the grub config
sudo grub-mkconfig -o /boot/grub/grub.cfg
# reboot the system
systemctl reboot
Test it with sudo systemctl hibernate
after you reboot once.
More Information: Swapfile — BTRFS documentation
Tips & Tricks
Don’t do a full balancing, it will break the swapfile
Thanks to @Zesko for pointing that out:
Running btrfs balance start --full-balance /
seems to rebalance everything and ignore the +C
(nodatacow) attribute at all, because you get this message in dmesg
if you activate a swapfile after doing a full balancing:
kernel: BTRFS warning (device XY): swapfile must not be copy-on-write
That means that every file regardless of the attribute seems to be relocated and converted to COW. That essentially breaks it.
Based on the comment of David Sterba using filters: btrfs balance -dusage=90 /
, it seems not to reach the swapfile and therefore does not affect it.
It is probably a bug, which have to be solved, but for now don’t balance or balance with care, that means with filters, if you use a swapfile on btrfs.
btrfs-assistant
is known to do a full balancing, which leads to the swap and hibernation problems as described.
This is a wiki article. You are free to copy, share, or edit the content without restrictions as long as it doesn’t miss the main topic.