[HowTo] Add a backing SWAP device to zram (and enable hibernation)

Introduction

What is zram? How to use it? Please see this related guide:

One of the main drawbacks to zram is its incompatibility with hibernation.
For this and other reasons zram users may wish to create an additional ‘backing’ SWAP device.

For quick-install steps skip to this section.


Creating a swap file

SWAP is a subject all its own, so for our purposes we will focus on the example of a swap file.

The ArchWiki has a handy introduction here:
https://wiki.archlinux.org/title/Swap#Swap_file

Instructions

Or follow the guide here.

Click to show

The first consideration is what size for the swap.

In order to ensure hibernation is successful even during the heaviest workloads it is advisable to make swap the size of your available RAM and zram combined.

Click to show calculation command

This bash string should calculate your total available ram, zram size, add them, and round up to the nearest whole number.

_hibned=$(awk "BEGIN {print $(zramctl | tail -1 | awk -F '[^0-9]*' '{ print $3 }')+$(awk '/MemTotal/ { printf "%.3f \n", $2/1024/1024 }' /proc/meminfo); exit}"); printf "%.0f\n" "$_hibned"

With this size in mind we can now create the swap file. We will assume 16gb here.

sudo mkswap -U clear --size 16G --file /swapfile

We will also want to add this swap to our /etc/fstab file.
The line should look like this. Note the priority. It should be lower than your zram priority.

/swapfile                                 none           swap    defaults,pri=0 0 0

After creating your backing swap file and adding it to /etc/fstab it is time to reboot!
Hibernation will now be possible while zram is used for SWAP.


Another word about priority

If you followed this guide and the zram guide then the priorities should already be acceptable.
The intention is to make sure that zram has a higher priority than the backing swap device. In the given example zram should have a priority of 100 and our /swapfile should have a priority of 0.
This ensures that during general operation the system will make use of the more performant zram and, because systemd automatically disregards zram while hibernating, the otherwise ignored /swapfile will be used for hibernation.


Quick Install

If you just want a few commands then these are for you.

Click to show
printf '\nFinding optimal swapfile size.\n'; _hibned=$(awk "BEGIN {print $(zramctl | tail -1 | awk -F '[^0-9]*' '{ print $3 }')+$(awk '/MemTotal/ { printf "%.3f \n", $2/1024/1024 }' /proc/meminfo); exit}"); _roundhibned=$(printf "%.0f\n" "$_hibned"); printf "\n%s""$_roundhibned"" GB\n\n"
printf '\nCreating swap file.\n\n'; sudo mkswap -U clear --size "$_roundhibned"G --file /swapfile; printf '\nDone.\n\n'
printf '\nAdding line to /etc/fstab.\n\n'; if [ "$(tail -c1 /etc/fstab; printf x)" != $'\nx' ]; then printf "\n" | sudo tee -a /etc/fstab; fi; printf '/swapfile                                 none           swap    defaults,pri=0 0 0\n' | sudo tee -a /etc/fstab; printf '\nDone.\n\nTime to REBOOT.\n\n'

Hibernation

Hibernation may require extra configuration.
In the case of a swap file, as is used the the examples above, refer to this guide:
[HowTo] Configure hibernation with a swap file


More Information

ArchWiki swapfile-zram hibernation page
Power management/Suspend and hibernate - ArchWiki

5 Likes

Thanks a lot for the quick install!
Been using separate partition as I used to do everything manually but this time I’m doing testing and the default install just makes one partition for everything so this saved me the reinstall or resizing the current partition and make a new one.
Pretty sweet contribution!

1 Like

Just to be clear … hibernation itself can require its own configurations depending on the system.
Please see the related guide on swap file hibernation here:

Seems on some machines using BTRFS there’s a proper command to create the swap file.

I qualified this with ‘some’ because on an Arch install with BTRFS I used the command as originally stated above and had no issues while on a Manjaro install with BTRFS I had to use the command’s btrfs version.


sudo btrfs filesystem mkswapfile --size 16G /swapfile

More info about this can be found at;
https://btrfs.readthedocs.io/en/latest/Swapfile.html#swapfile

EDIT: I should have read the BTRFS documentation closely. It turns out that if you place the swapfile in a subvolume then that subvolume will not be snapshotted (the eample above creates it in /) until swap is turned off.

This meant that as soon as I implemented it then timeshift-autosnap started to fail with;

errors
Creating new backup...(BTRFS)                                                                                                                 
Saving to device: /dev/sdXN, mounted at path: /run/timeshift/32222/backup                                                                     
Created directory: /run/timeshift/32222/backup/timeshift-btrfs/snapshots/{Date and Time}                                                 
E: ERROR: Could not create subvolume: Text file busy                                                                                          
                                                                                                                                              
E: btrfs returned an error: 256                                                                                                               
E: Failed to create subvolume snapshot: @                                                                                                     
Failed to create snapshot                                                                                                                     
------------------------------------------------------------------------------                                                                
Removing snapshots (incomplete):                                                                                                              
------------------------------------------------------------------------------                                                                
Removing snapshot: {Date and Time}
Deleted directory: /run/timeshift/32222/backup/timeshift-btrfs/snapshots/{Date and Time}
Removed snapshot:  {Date and Time}
------------------------------------------------------------------------------

thus

Steps to Correct;
  1. sudo swapoff - Turns off swap
  2. sudo rm -f /swapfile - Removes the swapfile
  3. sudo btrfs subvolume create /swap - Creates a BTRFS sub-volume exclusively for swap
  4. sudo btrfs filesystem mkswapfile --size 16G /swap/swapfile - Creates the swapfile as before but now in its own subvolume.
  5. sudo swapon /swap/swapfile - Turns on swap
  6. sudoedit /etc/fstab and add the following line;
# /swap/swapfile - (SWAP)
/swap/swapfile		none           swap    defaults,pri=0 0 0
  1. sudo systemctl daemon-reload - For systemd to reread the changed fstab file

This will ensure swap is turned on automatically at system startup using the swapfile on BTRFS subvolume and your autosnap snapshots will work as normal.