Hibernate in Fedora

I spent time yesterday making HybridSleep and Hibernate work in Fedora 32 on a ThinkPad X1 Carbon with an encrypted disk.

I don't ever plan to manually use hybrid-sleep or hibernate; I'd instead just lock my screen or close the laptop lid. So why bother to have these work?

It's because hybrid sleep and hibernate are useful to have when battery power runs out. You'll likely find in /etc/UPower/UPower.conf that your machine attempts hybrid-sleep, hibernate, and a full shutdown, in this order, when the battery runs out. If you don't want to lose working state, you need either a working hibernate or a working hybrid-sleep.

$ cat /etc/UPower/UPower.conf | tail -n 3
# If HybridSleep isn't available, Hibernate will be used
# If Hibernate isn't available, PowerOff will be used
CriticalPowerAction=HybridSleep
$

How to use this guide

There are typically 5-6 issues. Each of these is described below, along with steps to address them. I recommend incrementally addressing the issues and checking if hibernate works after each step — as opposed to implementing all fixes, some of which may turn out to be unnecessary in your case.

Does it already just work?

The first thing to do, before doing extra work, is to check whether hibernate already just works™ in your computer. If you're one of the lucky ones, then:

$ cat /sys/power/state
freeze mem disk
$

should include the output "disk". Next try:

# systemctl hibernate

Fingers crossed—your screen goes blank and your computer turns off. Turn on your computer again, log in as usual, and if your open windows were preserved you're good to go—hibernate worked! You should try the same with hybrid-sleep.

# systemctl hybrid-sleep

On the other hand, if the /sys/power/state output doesn't include "disk", and/or you see a failure message, you need to dig in further.

Sleep verb "hibernate" not supported

SecureBoot

One of the most common reasons for the inability to hibernate, and this is most likely true for Windows 8/10 laptops, is that SecureBoot is enabled. Disable SecureBoot in your BIOS; for my ThinkPad this involves:

As for whether you should disable SecureBoot, I recommend doing some research into this topic, since SecureBoot provides security benefits you might value over the ability to hibernate.

Once you've disabled SecureBoot, try systemctl hibernate again.

Insufficient swap

On to more gritty details. You should have swap space that matches or is larger than the total memory of your machine. Check swap size:

# swapon --show
NAME      TYPE      SIZE USED PRIO
/dev/dm-2 partition 2.2G   0B   -2

Check total memory size in unit kibibyte:

$ cat /proc/meminfo | grep MemTotal | awk '{ print $2 }'
16192912
$

If swap is insufficiently-sized you should disable the existing swap on the running system:

# swapoff /dev/dm-2
#

and disable it for future boots by deleting the corresponding entry from /etc/fstab.

Now add a sufficiently-sized swap file. Here's a terse but accurate guide.

# dd if=/dev/zero bs=16192912 count=1024 |
    pv |
    dd of=/swapfile
# chmod 0600 /swapfile
# mkswap /swapfile
# swapon /swapfile
#

Enable the swap file for future boots in /etc/fstab:

/swapfile swap swap defaults 0 0

GRUB

Next up, grub has to know to resume from your swap partition.

$ cat /etc/default/grub

Inspect the contents of GRUB_CMDLINE_LINUX.

GRUB_CMDLINE_LINUX="resume=/dev/mapper/fedora_localhost--live-swap rd.lvm.lv=fedora_localhost-live/root rd.luks.uuid=luks-0962d4ff-5b38-4a4e-99e3-30509326c9b1 rd.lvm.lv=fedora_localhost-live/swap rhgb quiet"

The important parts required here are the resume parameter and the rd.lvm.lv parameter for swap. Their actual values might be different for you. If either of resume or rd.lvm.lv for swap is missing, you should add it. But first you need to determine the values to use.

For resume, the value can be found by running the following command. In this example, the value is /dev/mapper/fedora_localhost--live-swap.

# systemctl list-units | grep swap
dev-mapper-fedora_localhost\x2d\x2dlive\x2dswap.swap  loaded active active  /dev/mapper/fedora_localhost--live-swap
swap.target  loaded active active  Swap

For rd.lvm.lv for swap, the value can be found by running the following command. In this example, the value is fedora_localhost-live/swap.

# lvscan
  ACTIVE  '/dev/fedora_localhost-live/swap' [7.72 GiB] inherit
  ACTIVE  '/dev/fedora_localhost-live/home' [<102.84 GiB] inherit
  ACTIVE  '/dev/fedora_localhost-live/root' [<69.99 GiB] inherit

If you're using a swap file, as opposed to a swap partition, you additionally need the resume_offset parameter. The value is can be found by running the following command. In the command output the value you're looking for is the first number, without the trailing dots, under the physical_offset column. If there are multiple lines of output, use only the first line.

# filefrag -v /swapfile

After you've updated GRUB_CMDLINE_LINUX in /etc/default/grub, you must generate grub.cfg to reflect the update. Assuming you're using a UEFI computer, which most modern computers are, run:

# grub2-mkconfig -o /etc/grub2-efi.cfg

dracut

Finally, the initramfs, which is managed by dracut. Start by running:

# dracut --print-cmdline

The output (formatted here for readability), if set up correctly for hibernate, should include the resume parameter.

rd.luks.uuid=luks-0962d4ff-5b38-4a4e-99e3-30509326c9b1
rd.lvm.lv=fedora_localhost-live/swap
rd.lvm.lv=fedora_localhost-live/root
resume=/dev/mapper/fedora_localhost--live-swap
root=/dev/mapper/fedora_localhost--live-root
rootfstype=ext4 rootflags=rw,relatime,seclabel

If it doesn't, you may need to add "resume" to the list of dracut modules. Create /etc/dracut.conf.d/resume.conf with the following content. See the man page for dracut.conf to learn more.

add_dracutmodules+=" resume "

Regenerate the initramfs:

# dracut -fv

and check that the resume parameter is now included.

TODO(nishanths): does this need to list the resume_offset parameter?

With all this done you should be ready to try systemctl hibernate again, which, fingers crossed, now works.

More Resources

https://bugzilla.redhat.com/show_bug.cgi?id=1206936

https://ask.fedoraproject.org/t/howto-hibernate-into-swap-file/6542