09 April 2024
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.
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.
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
2f29b7c3-cfdb-44a0-9ec6-2f141b7f581e
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.
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
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.
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.
As of 2024-09-09 this bug is resolved and the above steps work again. To confirm the system has the fix:
apt list --installed
initramfs-tools/noble-updates,noble-updates,now 0.142ubuntu25.2 all [installed,automatic]
Ensure the version is 0.142ubuntu25.2 or greater.
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;
}
});
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:
[Sleep]
#AllowSuspend=yes
#AllowHibernation=yes
#AllowSuspendThenHibernate=yes
#AllowHybridSleep=yes
#SuspendMode=
#SuspendState=mem standby freeze
#HibernateMode=platform shutdown
#HibernateState=disk
#HybridSleepMode=suspend platform shutdown
#HybridSleepState=disk
#HibernateDelaySec=180min
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!