Add support for hibernate
We need to do some setup to enable hibernate. Currently, this is the error message:
systemctl hibernate
Call to Hibernate failed: Not enough suitable swap space for hibernation available on compatible block devices and file systems
We need a swap file that's the same size as the memory on the system for this to work.
The following may be useful for computing swapfile size:
SWAP_SIZE=$(free | awk '/Mem/ {x=$2/1024/1024; printf "%.0fG", (x<2 ? 2*x : x<8 ? 1.5*x : x) }')
Should probably be optional during install. I don't want a 64G swap file 🤣
This may not be the ideal solution; however, you may suspend first and then hibernate. This shouldn't use nearly as much swap?
systemctl suspend-then-hibernate
Sharp Edges
- Btrfs swap does not support hibernate mode unless compression is disabled: https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate#Hibernation_with_a_swap_file_on_Btrfs
Potential solution
We could create dynamic swap based on the current memory usage, mirror that size, and hibernate? Here is a rough example
#!/usr/bin/env bash
#
# dynswap: Create a swapfile sized to current RAM usage (+ margin) for hibernation
# Tested on Arch Linux. Run as root.
set -euo pipefail
MARGIN_PCT=20 # % safety buffer above current used RAM
SWAPFILE=/swapfile # path to swap file
FSTAB=/etc/fstab # fstab path
## 1. Gather current RAM usage (in MiB) ########################################
# 'free --mebi' prints MiB units; field 3 in Mem row = used
USED_MIB=$(free --mebi | awk '/^Mem:/ {print $3}')
if [[ -z "$USED_MIB" ]]; then
echo "Could not determine used memory" >&2; exit 1
fi
## 2. Calculate swap size with margin ##########################################
SWAP_SIZE_MIB=$(( USED_MIB + (USED_MIB * MARGIN_PCT / 100) ))
echo "Current RAM used: ${USED_MIB} MiB, creating ${SWAP_SIZE_MIB} MiB swapfile."
## 3. Disable and remove any existing swapfile #################################
if swapon --summary | grep -q "$SWAPFILE"; then
swapoff "$SWAPFILE"
fi
rm -f "$SWAPFILE"
## 4. Create the new swapfile ##################################################
fallocate -l "${SWAP_SIZE_MIB}M" "$SWAPFILE"
chmod 600 "$SWAPFILE"
mkswap "$SWAPFILE"
## 5. Activate swap ############################################################
swapon "$SWAPFILE"
## 6. Ensure /etc/fstab entry exists ###########################################
if ! grep -q "^$SWAPFILE" "$FSTAB"; then
echo -e "$SWAPFILE\tnone\tswap\tdefaults\t0 0" >> "$FSTAB"
echo "Added $SWAPFILE to $FSTAB"
fi
## 7. Show result ##############################################################
echo "Swap now active:"
swapon --show
echo "Done. Remember to keep your GRUB resume=/resume_offset=… parameters updated!
If you re-created the file, run:
filefrag -v $SWAPFILE | grep \" 0:\" | awk '{print \$4}' | cut -d. -f1
and update resume_offset in /etc/default/grub, then regenerate grub.cfg."
exit 0
systemd supports hibernation to a regular file.
# Enable hibernation to a regular file
sudo systemctl enable systemd-hibernate-resume
# Uses /var/lib/systemd/sleep/ for hibernation storage
Problem is that default swap file is only 4G. Far short of most people's RAM. So that's part of what needs to change.
Problem is that default swap file is only 4G. Far short of most people's RAM. So that's part of what needs to change.
The swap omarchy already have - is not the swap file, it's zram. Zram is stored in RAM, so hibernation (sleep to disk) with it is absolutely not possible.
It comes by default with Arch and is brought up by [email protected] with default config:
~ > cat /etc/systemd/zram-generator.conf
[zram0]
If we want to make hibernation possible while keeping zram as swap, we need to:
- Create a swap file. Btrfs#Swap File - ArchWiki
- To not use a slower swapfile instead of faster zram, we need to have a lower
priority for the swapfile. It can be done like that in/etc/fstab:
/swap/swapfile none swap defaults,pri=0 0 0
But probably it's not even needed, because man swapon(8) says that:
When no priority is defined, Linux kernel defaults to negative numbers.
And the man zram-generator.conf(5) says:
• swap-priority=
Controls the relative swap priority, a value between -1 and 32767. Higher numbers indicate higher priority.
If unset, 100 is used.
So by default, zram will have a higher priority and be used first.
3. We need to enable the resume hook in initrafms Suspend and hibernate#Configure_the_initramfs - ArchWiki
- Ensure tht
/usr/lib/systemd/system-generators/systemd-hibernate-resume-generatorexists - it enables thesystemd-hibernate-resume.service( By defaultsystemctl hibernatewill automatically pick a suitable swap space to hibernate into, and put the information of the used swap space to theHibernateLocationEFI variable. When the system will bootsystemd-hibernate-resume.servicewill readHibernateLocationEFI variable and resume the system from it.)
After that, hibernation will work properly
If needed, I can add scripts for this; it's actually quite simple. But I need to understand whether adding the swap file should be optional? If so, what would be the mechanism for this optionality?
@killeik can you provide the scripts? I already have the swapfile that 2x my current RAM. I need the instruction of later part. Because I can't get it working or not sure if I'm done right. Tks!
This script was written with llm assist, but I have read it more than 10 times and added all the necessary reasonable checks, so it should not harm the system. I have also tested it several times on my system with omarchy 2.0
Important note: it will only work on systems with limine as the bootloader and if no swap file has been created previously. @nielpattin In your specific case, please delete the existing swap file so that the script can recreate it to match the size of your RAM.
And as always, read the scripts before executing them, and be really careful if you have important, unbacked-up data on your system.
UPD: use script from #1417 it's handwritten and just better
Btrfs cannot snapshot subvolumes containing an active swapfile. To enable hibernation without breaking snapshot functionality we should place the swapfile on its own dedicated btrfs subvolume. Otherwise, the root subvolume will no longer be snapshottable.
Related effort on snapshots: https://github.com/basecamp/omarchy/issues/722 https://github.com/basecamp/omarchy/pull/998
This script was written with llm assist, but I have read it more than 10 times and added all the necessary reasonable checks, so it should not harm the system. I have also tested it several times on my system with omarchy 2.0
where does this stand? im eager to try out this script.
what would we need to implement this in omarchy?
what would we need to implement this in omarchy?
Nothing really, so I made PR #1417 :D
I used to make it work and it was so cool to have you laptop last for weeks without recharging!!!
Working on it in https://github.com/basecamp/omarchy/pull/1417 👌