Hibernation in Fedora Workstation

Photo by Beth Jnr on Unsplash

This article walks you through the manual setup for hibernation in Fedora Linux 36 Workstation using BTRFS and is based on a gist by eloylp on github.

Goal and Rationale

Hibernation stores the current runtime state of your machine – effectively the contents of your RAM, onto disk and does a clean shutdown. Upon next boot this state is restored from disk to memory such that everything, including open programs, is how you left it.

Fedora Workstation uses ZRAM. This is a sophisticated approach to swap using compression inside a portion of your RAM to avoid the slower on-disk swap files. Unfortunately this means you don’t have persistent space to move your RAM upon hibernation when powering off your machine.

How it works

The technique configures systemd and dracut to store and restore the contents of your RAM in a temporary swap file on disk. The swap file is created just before and removed right after hibernation to avoid trouble with ZRAM. A persistent swap file is not recommended in conjunction with ZRAM, as it creates some confusing problems compromising your systems stability.

A word on compatibility and expectations

Hibernation following this guide might not work flawless on your particular machine(s). Due to possible shortcomings of certain drivers you might experience glitches like non-working wifi or display after resuming from hibernation. In that case feel free to reach out to the comment section of the gist on github, or try the tips from the troubleshooting section at the bottom of this article.

The changes introduced in this article are linked to the systemd hibernation.service and hibernation.target units and hence won’t execute on their own nor interfere with your system if you don’t initiate a hibernation. That being said, if it does not work it still adds some small bloat which you might want to remove.

Hibernation in Fedora Workstation

The first step is to create a btrfs sub volume to contain the swap file.

$ btrfs subvolume create /swap

In order to calculate the size of your swap file use swapon to get the size of your zram device.

$ swapon
NAME       TYPE      SIZE USED PRIO
/dev/zram0 partition   8G   0B  100

In this example the machine has 16G of RAM and a 8G zram device. ZRAM stores roughly double the amount of system RAM compressed in a portion of your RAM. Let that sink in for a moment. This means that in total the memory of this machine can hold 8G * 2 + 8G of RAM which equals 24G uncompressed data. Create and configure the swapfile using the following commands.

$ touch /swap/swapfile
# Disable Copy On Write on the file
$ chattr +C /swap/swapfile
$ fallocate --length 24G /swap/swapfile
$ chmod 600 /swap/swapfile 
$ mkswap /swap/swapfile

Modify the dracut configuration and rebuild your initramfs to include the

resume
module, so it can later restore the state at boot.

$ cat <<-EOF | sudo tee /etc/dracut.conf.d/resume.conf
add_dracutmodules+=" resume "
EOF
$ dracut -f

In order to configure grub to tell the kernel to resume from hibernation using the swapfile, you need the UUID and the physical offset.

Use the following command to determine the UUID of the swap file and take note of it.

$ findmnt -no UUID -T /swap/swapfile
dbb0f71f-8fe9-491e-bce7-4e0e3125ecb8

Calculate the correct offset. In order to do this you’ll unfortunately need gcc and the source of the btrfs_map_physical tool, which computes the physical offset of the swapfile on disk. Invoke gcc in the directory you placed the source in and run the tool.

$ gcc -O2 -o btrfs_map_physical btrfs_map_physical.c
$ ./btrfs_map_physical /path/to/swapfile

FILE OFFSET  EXTENT TYPE  LOGICAL SIZE  LOGICAL OFFSET  PHYSICAL SIZE  DEVID  PHYSICAL OFFSET
0            regular      4096          2927632384      268435456      1      <4009762816>
4096         prealloc     268431360     2927636480      268431360      1      4009766912
268435456    prealloc     268435456     3251634176      268435456      1      4333764608
536870912    prealloc     268435456     3520069632      268435456      1      4602200064
805306368    prealloc     268435456     3788505088      268435456      1      4870635520
1073741824   prealloc     268435456     4056940544      268435456      1      5139070976
1342177280   prealloc     268435456     4325376000      268435456      1      5407506432
1610612736   prealloc     268435456     4593811456      268435456      1      5675941888

The first value in the PHYSICAL OFFSET column is the relevant one. In the above example it is 4009762816.

Take note of the pagesize you get from getconf PAGESIZE.

Calculate the kernel resume_offset through division of physical offset by the pagesize. In this example that is 4009762816 / 4096 = 978946.

Update your grub configuration file and add the resume and resume_offset kernel cmdline parameters.

grubby --args="resume=UUID=dbb0f71f-8fe9-491e-bce7-4e0e3125ecb8 resume_offset=2459934" --update-kernel=ALL

The created swapfile is only used in the hibernation stage of system shutdown and boot hence not configured in fstab. Systemd units control this behavior, so create the two units hibernate-preparation.service and hibernate-resume.service.

$ cat <<-EOF | sudo tee /etc/systemd/system/hibernate-preparation.service
[Unit]
Description=Enable swap file and disable zram before hibernate
Before=systemd-hibernate.service

[Service]
User=root
Type=oneshot
ExecStart=/bin/bash -c "/usr/sbin/swapon /swap/swapfile && /usr/sbin/swapoff /dev/zram0"

[Install]
WantedBy=systemd-hibernate.service
EOF
$ systemctl enable hibernate-preparation.service
$ cat <<-EOF | sudo tee /etc/systemd/system/hibernate-resume.service
[Unit]
Description=Disable swap after resuming from hibernation
After=hibernate.target

[Service]
User=root
Type=oneshot
ExecStart=/usr/sbin/swapoff /swap/swapfile

[Install]
WantedBy=hibernate.target
EOF
$ systemctl enable hibernate-resume.service

Systemd does memory checks on login and hibernation. In order to avoid issues when moving the memory back and forth between swapfile and zram disable some of them.

$ mkdir -p /etc/systemd/system/systemd-logind.service.d/
$ cat <<-EOF | sudo tee /etc/systemd/system/systemd-logind.service.d/override.conf
[Service]
Environment=SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1
EOF
$ mkdir -p /etc/systemd/system/systemd-hibernate.service.d/
$ cat <<-EOF | sudo tee /etc/systemd/system/systemd-hibernate.service.d/override.conf
[Service]
Environment=SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1
EOF

Reboot your machine for the changes to take effect. The following SELinux configuration won’t work if you don’t reboot first.

SELinux won’t like hibernation attempts just yet. Change that with a new policy. An easy although “brute” approach is to initiate hibernation and use the audit log of this failed attempt via audit2allow. The following command will fail, returning you to a login prompt.

systemctl hibernate

After you’ve logged in again check the audit log, compile a policy and install it. The -b option filters for audit log entries from last boot. The -M option compiles all filtered rules into a module, which is then installed using semodule -i.

$ audit2allow -b
#============= systemd_sleep_t ==============
allow systemd_sleep_t unlabeled_t:dir search;
$ cd /tmp
$ audit2allow -b -M systemd_sleep
$ semodule -i systemd_sleep.pp

Check that hibernation is working via systemctl hibernate again. After resume check that ZRAM is indeed the only active swap device.

$ swapon
NAME       TYPE      SIZE USED PRIO
/dev/zram0 partition   8G   0B  100

You now have hibernation configured.

GNOME Shell hibernation integration

You might want to add a hibernation button to the GNOME Shell “Power Off / Logout” section. Check out the extension Hibernate Status Button to do so.

Troubleshooting

A first place to troubleshoot any problems is through journalctl -b. Have a look around the end of the log, after trying to hibernate, to pin-point log entries that tell you what might be wrong.

Another source of information on errors is the Problem Reporting tool. Especially problems, that are not common but more specific to your hardware configuration. Have a look at it before and after attempting hibernation and see if something comes up. Follow up on any issues via BugZilla and see if others experience similar problems.

Revert the changes

To reverse the changes made above, follow this check-list:

  • remove the swapfile
  • remove the swap subvolume
  • remove the dracut configuration and rebuild dracut
  • remove kernel cmdline args via grubby –remove-args=
  • disable and remove hibernation preparation and resume services
  • remove systemd overrides for systemd-logind.service and systemd-hibernation.service
  • remove SELinux module via semodule -r systemd_sleep

Credits and Additional Resources

This article is a community effort based primarily on the work of eloylp. As author of this article I’d like to make transparent that I’ve participated in the discussion to advance the gist behind this but many more minds contributed to make this work. Make certain to check out the discussion on github.

There are already some ansible playbooks and shell scripts to automate the process depicted in this guide. For example check out the shell scripts by krokwen and pietryszak or the ansible playbook by jorp

See the arch wiki for the full guide on how to calculate the swapfile offset.

Fedora Project community

45 Comments

  1. usando Fedora Plasma ,certo que aqui diz suspender ,que na realidade e hibernação ,realmente sistema ótimo ,pós desligar o computador fica muito demorado seu inicio ,obrigado

  2. Oscar

    Hello. A very interesting article.

    One question, though: I have a Fedora 36 system installed on a regular Ext4 partition and I don’t use ZRAM. With this configuration, if stock Systemd-hibernate service is running… in what file it dumps the RAM content?

    I’d wanted to get it from a disk image to analyze with Volatility but I’ve not been able to find it (I’ve searched in systemd-sleep.conf file but there’s no related directive)

    Thanks!

    PD: I asked this question here, too: https://unix.stackexchange.com/questions/712163/in-what-file-systemd-hibernate-service-dumps-the-ram-content

    • On hibernation your RAM contents are put into the swap file, so if you already use one you have to make sure the file is big enough to store your RAM contents. You would probably create a second swap file which can take both your RAM and your default swap file and as it is done in this article activate / deactivate this second swap file on hibernation / resume.

      This is an educated guess though. I’m not entirely sure of it.

  3. Henri

    “In this example the machine has 16G of RAM and a 8G zram device. ZRAM stores roughly double the amount of system RAM compressed in a portion of your RAM. Let that sink in for a moment. This means that in total the memory of this machine can hold 8G * 2 + 8G of RAM which equals 24G uncompressed data.”

    Q: 16Gb (RAM) + 2 * 8Gb (zram device) = at least 32Gb … Am I missing something?

    • Xtrondo

      The total ram of the example machine is 16GB with 8G (of those 16G as Zram)

    • Marcus

      I’ll argue that this is a misrepresentation of what is technically possible.

      ZRAM doesn’t generally store with a compression factor of 50%, or any other fixed amount of data (make an experiment: malloc 4GB of ram, write it full of byte ‘c’: that will have a much higher compression ratio. Same experiment, but fill the memory with pseudorandom numbers; ZRAM, like any other compressor, cannot possibly compress that).

      That 50% might be an experience-based value, maybe, probably for typical workstation loads (I doubt it has been found in a large-scale study).

      How much you can or can’t compress memory pages of course depends on the entropy in these pages, and that will be wildly different depending on whether these pages contain repetitive data or e.g. already compressed image content (which I find a relatively likely content for modern workstations).

      • You are right. The value of 50% is an over-simplification which I and some others found to work, though this is neither tested in a large scale study nor is it technically accurate. If you have a better understanding of this and maybe also a better estimate on how much memory one has to allocate for the swap file I’ll probably update the article. The target value for the swap file should be a sane maximum size that “normal” RAM and uncompressed ZRAM can occupy.

        • Michael J Gruber

          The amount of RAM that

          swapon

          and

          zramctl

          (disksize column) display is the amount of data that the (zram) swap can hold, not the amount of RAM that is used up by zram. That is: zram swap of disksize 8GB will use at most 8GB of RAM (uncompressed) but typically at most 4GB (compression ratio 2:1). That is why Fedora 34 and up has zram size = RAM size (up to 8GB).

          So, for your machine with 16GB RAM and 8GB zram, zram will use at most 8GB of your 16GB but typically only 4Gb even if the zram is “full” (but compressed). In any case, since zram is stored in RAM, storing the RAM (which includes zram) on hibernate would be enough – if only hibernate knew to store the RAM in a separate file.

          But to direct hibernate to use the right (non-RAM file), one has to turn zram off, which moves zram swap to the non-RAM swap file. At worst, that means

          disksize

          data (8GB); again, in the worst case zram compressed those 8GB perfectly leaving almost all of the RAM unused, and again at worst you filled up all of the remaining RAM. So the theoretical maximum to store in the extra swapfile is really RAM size + zram disksize (+ possibly overhead/graphics card RAM).

  4. Mika

    Great post! Will this work well too if my Fedora Workstation installation is encrypted? Thanks

    • Short answer: Yes, this also works if your disk is encrypted.

      Long answer: since the swap file is stored on the encrypted disk and storage / resume happen right before the lock and just after the unlock in the dracut image this also works on encrypted storage.

  5. Marcus

    Stupid question: BTRFS is default on new fedora installations, right? How come not having hibernation work out of the box wasn’t a blocking bug when migrating to btrfs-by-default for F33?

    I’m thankful for this guide, but if I act as if I’m an average-Joe kind of user, the hurdles I’d have to jump according to it are quite in-my-face as “fedora doesn’t actually support hibernation in a default installation

    • sean o

      Hibernate is sketchy to begin with hibernate and suspend, and didn’t work on a number of machines. It is implemented by the vender and it isn’t a standard and not all machines are supported. Then there was a move to some default hybrid version. But the bottomline is if it was a blocking bug, then we would still be on Fedora 1.

      • Marcus

        “It is hard, therefore it can’t be a feature we require to work” doesn’t sound convincing to me, to be honest.

        How is hibernate sketchy? Other operating system (Windows on the forefront, certainly) do it, out of the box, instantly, we much less control over device drivers. Honestly, my kernel seems to do most of it quite flawlessly, it’s that the boot/userland tooling around it are not up to the task.

        • Michael Gruber

          In fact, hibernate to disk does not require any hardware support at all. The OS just needs to store RAM and configure the kernel to restore it. You need hardware support only if you want other ways to resume (than by power button/boot) or hybrid suspend/hibernate.

  6. Johndoe

    Does this work wrt secure boots?

  7. SigmaSquadron

    On the instructions to create a swap device, it’s best to

    dd

    from /dev/zero instead of using fallocate, as fallocate creates holes in the file, which may break

    mkswap

    and

    swapon

    .

  8. hibernação foi um grande passo tanto da tecnologia de ponta ,como dar uma pausa para todo circuito eletrico do computador ,e ajudar no tempo de ligar o computador ,ou fica hibernando ,sem dar tanto desgaste dos seus componentes

  9. Darvond

    Is it really healthy for SSDs to do hibernation? That’s been a concern of mine.

    • An educated guess, I’m not 100% sure of it: as the swap file is only created before and after hibernation and as you don’t do hibernation like every few minutes / seconds it should be reasonably safe. Unlike using a swap file on SSD as regular swap device, where your concern is coming from I presume

  10. Yavuz

    I followed each step in the article and works like a charm. I was looking forward for a proper hibernation for some time. This is it.

    ACER SWIFT S3
    F36 KDE

  11. na verdade temos de encontrar uma forma mais façil de se fazer o download do sistema linux onde aqui no Brasil usamos o tal cd dvd ,e na verdade esconde de muita gente as facilidades do sistema ,certo que estamos crescendo muito

  12. Andrew

    What about suspend?

    • What about it? 🙂 Depending on your hardware model and driver capabilities (e.g. can it do power-state S3?) suspend is already possible. At least on my Thinkpad X1 suspend is a native option, without further setup required.

  13. Waethorn

    Does this mean that there’s no memory-safe sleep option (i.e. “hybrid sleep”) out of the box? This seems like a big omission considering all other OS’s already have this after running into corruption issues over the years with just standard S3 Suspend-to-RAM options and a power loss, or some other power management fault where the system fails to resume correctly.

  14. joe

    Tldr; don’t use btrfs if you have a limited storage configuration, like any off-the-shelf mid-tier laptop…

    Seems like a MASSIVE oversight by the Fedora team.

    • konradmb

      W-What? The only difference here between ext4 and btrfs in this scenario is usage of

      btrfs_map_physical.c

      instead of

      filefrag -v

      . I know how the rest goes because I’ve done the same thing in Ubuntu a few years ago (on ext4).
      Arch wiki says that swap file support in btrfs is available since kernel 5.0. And even if you wanted to have <5.0 kernel with btrfs and hibernation, then you could use separate swap partition.

  15. BattlePeasant

    The idea behind hibernation is to store an image of the memory on disk and then load it as it is. So why is it necessary to uncompress ZRAM? Why not store it as is? Then 16 GB of memory will take up exactly 16 GB of disk space.
    This is an idea for developers, I don’t use ZRAM, I use swap and hibernate works fine.

  16. foo bar

    My whole file system was heavily damaged after this howto. First time in ages I had to reinstall.

  17. Grzegorz

    Hi,
    What if somebody has 128 GB RAM?

  18. realmente bombando de tecnologias de ponta ,nosso sistema Fedora está bem a frente de outros sistemas ,pós nossa hibernação seria um descanso do computador ou o sistema armazena todos seu contéudo ,e ao iniciar ali está como e nosso desejo

  19. I am using Fedora Linux 36 Workstation using BTRFS on my oldish Toshiba laptop. I have a 500GBt SSD installed and Hybernation works perfectly right “out of the box” – am I missing something?

    My system: Operating System: Fedora Linux 36
    KDE Plasma Version: 5.25.4
    KDE Frameworks Version: 5.96.0
    Qt Version: 5.15.5
    Kernel Version: 5.18.16-200.fc36.x86_64 (64-bit)
    Graphics Platform: X11
    Processors: 4 × Intel® Core™ i5-2467M CPU @ 1.60GHz
    Memory: 9,6 GiB of RAM
    Graphics Processor: Mesa Intel® HD Graphics 3000
    Manufacturer: TOSHIBA
    Product Name: PORTEGE Z830
    System Version: PT224E-00G00JCE

  20. Giovanni Pelosi

    But which is the critical memory limit for hibernation?

    More RAM you have, more you have to save …
    How much I/O dots the boot take?

    SSD Lifetime vs Laptop Batteries …

    It looks like a “session restore” topic
    (I never found it too useful, aside browsers and IDEs …)

  21. PA Cordonnier

    Hi,
    Thanks a lot for this article ! It worked like a charm for me !

    Fedora 35
    Dell precision 5520
    My disk is encrypted

    It used to work (natively ?) on my previous installation fedora 29-30 I think. I’m very happy to make it work again ! Hibernation is so useful.

  22. gjason

    I really wanted this to work, but it won’t for me. Running

    systemctl hibernate

    gives me

    Failed to hibernate system via logind: Sleep verb "hibernate" not supported

    Inspecting the results of

    journalctl -b

    I see lots of

    kernel: Lockdown: systemd-logind: hibernation is restricted; see man kernel_lockdown.7

    When I check that man page, I see that it says

    Unencrypted hibernation/suspend to swap are disallowed as the kernel image is saved to a medium that can then be accessed.

    I’m assuming this is because I chose not to encrypt my filesystem? Can I just enable encryption on the

    /swap

    drive?

  23. konradmb

    Isn’t it counterproductive to do

    /usr/sbin/swapoff /dev/zram0

    before hibernation? If zram is stored in RAM (compressed with LZO by default), then it would uncompress data to disk (swapfile), and then recompress it in kernel with LZO again to hibernation image.

    Wouldn’t it be better to just leave zram on, as its contents are all in RAM already, so it would end up in hibernation image anyway?

  24. Andy

    Tried to follow this guide, but I’m stuck at the end by audit2allow. When I run the command, I get just two empty lines and the followup command fails due to ‘syntax error’ at token ” on line 6, followed again by two empty lines. Any ideas?

  25. Jia Yuan Lo

    Upgrade to kernel 5.19.4-200.fc36.x86_64 and I can no longer boot normally, end up at emergency boot
    Reverting back to kernel 5.18.18-200.fc36.x86_64 still worked

    • Jia Yuan Lo

      Nvm, I narrow down to kernel itself that has issue.
      After removing “resume=” and “resume_offset=”, it still wont boot. 🙁

Comments are Closed

The opinions expressed on this website are those of each author, not of the author's employer or of Red Hat. Fedora Magazine aspires to publish all content under a Creative Commons license but may not be able to do so in all cases. You are responsible for ensuring that you have the necessary permission to reuse any work on this site. The Fedora logo is a trademark of Red Hat, Inc. Terms and Conditions

%d bloggers like this: