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.
2022-12-11 UPDATE: There is a new rather severe caveat to this article. If Secure Boot is enabled and the kernel boots in lockdown mode, hibernation does not work as long as the kernel does not support signed hibernation images.
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
$ 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.
newton
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
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
Alexander Wellbrock
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.
Osqui
Ok, understood! Thanks a lot!
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).
Alexander Wellbrock
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
and
(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
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).
Mika
Great post! Will this work well too if my Fedora Workstation installation is encrypted? Thanks
Alexander Wellbrock
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.
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.
Johndoe
Does this work wrt secure boots?
Alexander Wellbrock
Yes, it does
SigmaSquadron
On the instructions to create a swap device, it’s best to
from /dev/zero instead of using fallocate, as fallocate creates holes in the file, which may break
and
.
Alexander Wellbrock
Thanks for this helpful comment!
Marcus
btrfs should detect zero blocks, don’t think this makes a practical difference
newton
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
Darvond
Is it really healthy for SSDs to do hibernation? That’s been a concern of mine.
Alexander Wellbrock
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
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
Alexander Wellbrock
Nice! Glad to hear it’s working for you as expected 🙂
newton
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
Andrew
What about suspend?
Alexander Wellbrock
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.
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.
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
instead of
. 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.
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.
foo bar
My whole file system was heavily damaged after this howto. First time in ages I had to reinstall.
Gregory Bartholomew
Sorry to hear that. Was there a particular command that deserves a special warning or caution note in the howto?
Grzegorz
Hi,
What if somebody has 128 GB RAM?
newton
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
Stan Sykes
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
konradmb
Do you have a separate swap partition?
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 …)
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.
gjason
I really wanted this to work, but it won’t for me. Running
gives me
Inspecting the results of
I see lots of
When I check that man page, I see that it says
I’m assuming this is because I chose not to encrypt my filesystem? Can I just enable encryption on the
drive?
konradmb
Isn’t it counterproductive to do
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?
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?
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. 🙁