09 April 2024

Hibernate on Ubuntu 22.04 and 24.04 without uswsusp

Getting my laptop to hibernate successfully with Ubuntu 22 was a little tricky.

Most of the online resources mention a command swap-offset which I think comes from the package uswsusp. That package is no longer part of Ubuntu.

These are the steps I used to get Hibernate working on a Lenovo T490 with Ubuntu 22.

Sizing the Swap File

Ubuntu installs a small swapfile by default (2GB on my system) rather than a swap partition.

The swapfile needs to be at least as large as the system memory.

First check the size of current swap:

$ swapon -s
Filename                Type        Size        Used        Priority
/swapfile                               file        16778236    0       -2

# Or alternatively check swap and memory size together:

$ free -m
               total        used        free      shared  buff/cache   available
Mem:           15640        1755       10890         581        2994       12994
Swap:          16384           0       16384

Here we can see the total system memory is just under 16GB and the swap file is sized at 16GB as I have already sized it to be at least as large as memory. To resize swap:

sudo swapoff -a
sudo dd if=/dev/zero of=/swapfile bs=1M count=16385
sudo mkswap /swapfile
sudo swapon /swapfile

Then restart the system.

Swapfile Details

To enable hibernate, you need know the UUID of the partition the swapfile resides on, and the offset of the swapfile on the partition.

To get the partition UUID:

$ findmnt -no UUID -T /swapfile

To get the offset:

$ sudo filefrag -v /swapfile
Filesystem type is: ef53
File size of /swapfile is 17180917760 (4194560 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..   12287:   39702528..  39714815:  12288:            
   1:    12288..   14335:    1984512..   1986559:   2048:   39714816:
   2:    14336..   16383:   39825408..  39827455:   2048:    1986560:
   3:    16384..   18431:   39829504..  39831551:   2048:   39827456:
   4:    18432..   22527:   39839744..  39843839:   4096:   39831552:

The offset you want is the first physical offset from the first line, ie 39702528.

Update Grub2

Next, update the grub boot options using the value obtain above. Edit /etc/default/grub and find the line that looks like GRUB_CMDLINE_LINUX_DEFAULT="quiet splash. Edit the line so it looks like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=UUID=2f29b7c3-cfdb-44a0-9ec6-2f141b7f581e resume_offset=39702528"

Note that the resume line looks like resume=UUID=2f..., as I missed the UUID part on my first try at setting this up. Then run:

sudo update-grub

Next edit sudo vi /etc/initramfs-tools/conf.d/resume and add:

RESUME=UUID=2f29b7c3-cfdb-44a0-9ec6-2f141b7f581e resume_offset=39702528

In any guides I found, the first RESUME was always in uppercase. I am not sure if it must be or not.

Now, run:

sudo update-initramfs -c -k all

At this stage reboot, then you should be able to hibernate via:

sudo systemctl hibernate

Hibernate From The UI

My Ubuntu runs the Gnome desktop environment (this must be the default, as I did not select it). To get the hibernate option from the usual power menu, you can add a Gnome extension. First, enable Firefox to install the extensions:

sudo apt install gnome-shell-extensions
sudo apt install chrome-gnome-shell

Logout, then install the Gnome Shell Integration extension.

Restart Firefox and install the status button extension, and toggle it ON.

Then logout and in again and the Hibernate and Hybrid Sleep options should be available.

Updates for Ubuntu 24.04

On Ubuntu 24.04, a few things have changed.

First, the default swapfile name has changed from swapfile to swap.img. I updated /etc/fstab to reference swapfile.

Second, the step sudo update-initramfs -c -k all is no longer required, or was never required!

Third, there seems to be a bug which causes an error:

systemctl hibernate
error: "Call to Hibernate failed: Invalid argument" 

This is apparently triggered by a kernel update. To fix it, remove the hibernate settings from /etc/default/grub reboot, and add them back again.

Fourth (and finally), the extension to enable the hibernate button in the boot menu did not work for me until I added the following found here to /etc/polkit-1/rules.d/10-enable-hibernate.rules:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.login1.hibernate" ||
        action.id == "org.freedesktop.login1.hibernate-multiple-sessions" ||
        action.id == "org.freedesktop.upower.hibernate" ||
        action.id == "org.freedesktop.login1.handle-hibernate-key" ||
        action.id == "org.freedesktop.login1.hibernate-ignore-inhibit")
        return polkit.Result.YES;

Hybrid Sleep

Googling about hybrid sleep suggests it is like suspend / sleep and hibernate together. The system memory state is kept for quick startup, but the memory is also persisted to disk in case of power failure.

With Windows 11 and this same laptop, when Windows sleeps it is initially suspended, but then hibernates after some time.

I figured the Linux Hybrid Sleep was like this, but initial testing and some research suggests it is not.

The Hybrid sleep settings can be controlled via /etc/systemd/sleep.conf, which defaults to 180 minutes:

#SuspendState=mem standby freeze
#HibernateMode=platform shutdown
#HybridSleepMode=suspend platform shutdown

I tried changing this to 5min, and the laptop did not hibernate even after 15 minutes. Some reports suggest this used to work this way, and no longer does. Other reports suggest the laptop will wake the system when the battery reaches 5% and then it will hibernate. For now I will leave this as a problem to be solved!

blog comments powered by Disqus