2023-07-13


Hibernation Debugging


Suspend and Hibernation

If you factor out Modern-Standby, modern computers have two commonly used sleep states: S3 (Suspend to ram) and S4 (Suspend to disk). In S3 state, a laptop has to constantly draw power from the battery to keep the ram sticks powered, so it will eventually run out of battery within a few hours or days.

To battle this limitation a hybrid mode got invented to switch from S3 to S4 after a couple of hours, after a certain amount of time passes, the computer gets woken up again and all ram content gets written to disk. After it can get powered off completely, no more drained batteries in exchange for slightly longer boot times.

My laptop could not do this for some reason, even though systemd has the "suspend-then-hibernate" functionality, and I never really figured out why. When I finally tried to force the laptop to execute this mode, the terminal just exited with:

1sudo systemctl suspend-then-hibernate
2Call to SuspendThenHibernate failed: Sleep verb "suspend-then-hibernate" not supported
Not supported

Why? A quick internet search just got me a pretty emotional reddit thread.

Debugging

suspend-then-hibernate is a functionality of systemd-logind, so I need to get some log output from it, but the default logger did not really help. A quick look at the source code revealed that there could be more detailed logging output if I set it to the "debug" level ... but how?

At first, I found that post, suggesting me to set the LogLevelMax value, but that did not work out. Another reply inside a mailing-list from the man himself got it working, now I had plenty of debug output

On Fri, 29.03.13 11:13, Manuel Reimer (Manuel.Spam at nurfuerspam.de) wrote:

> Hello,
> 
> I want to find out why inhibiting the power button doesn't work
> "system wide". As first step, I want to compare debug messages,
> logged by logind.
> 
> But unfortunately I don't manage to get them logged to somewhere.
> Enabling debug output for systemd seems to not enable debug output
> for logind. Currently, I use both, the kernel parameter
> "systemd.log_level=debug" and the setting "LogLevel=debug" in
> /etc/systemd/system.conf.

That only enables debug logging for systemd itself, i.e. PID 1.

To enable debug logging for logind, please copy
/usr/lib/systemd/system/systemd-logind.service to
/etc/systemd/system/systemd-logind.service and then edit it there. Add
"Environment=SYSTEMD_LOG_LEVEL=debug" to the [Service] section.

Lennart

-- 
Lennart Poettering - Red Hat, Inc.
Debug output

The output said that some kind of swap-file offset could not be found, and that it is crucial to know it to save the rams content into it. As of now systemd seems to have no support to detect a swap-file on btrfs partitions

1 fd = open(swap->path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
2 if (fd < 0)
3 return log_debug_errno(errno, "Failed to open swap file %s to determine on-disk offset: %m", swap->path);
4
5 r = fd_verify_regular(fd);
6 if (r < 0)
7 return log_debug_errno(r, "Selected swap file is not a regular file.");
8
9 r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
10 if (r < 0)
11 return log_debug_errno(r, "Error checking %s for Btrfs filesystem: %m", swap->path);
12 if (r > 0) {
13 log_debug("%s: detection of swap file offset on Btrfs is not supported", swap->path);
14 *ret_offset = UINT64_MAX;
15 return 0;
16 }
17

The offset index variable stays 0 and systemd returns with an error message

1if (hibernate_location->offset == UINT64_MAX) {
2 if (sys_offset == 0)
3 return log_debug_errno(SYNTHETIC_ERRNO(ENOSYS), "Offset detection failed and /sys/power/resume_offset is not set.");
4
5 hibernate_location->offset = sys_offset;
6 }

There is a workaround for this described here, but it involves to set a certain environment variable that skips sanity checks, a little too risky for me, so I created a dedicated swap partition next to the root partition ... and ended up bricking my system anyway.

I managed to screw up the resume kernel parameter, rebooted the system to set it correctly, after a second reboot, the "old" persisted ram state got loaded which destroyed my btrfs partition.

Conclusion

Always have an up to date backup, I had one, but it was kinda old, I had to redo quite some stuff I did to my settings again, what sucked a little. Now, after years of draining the poor battery to death, I finally have the best of both worlds again, my laptop now switches to S4 after 45 minutes being in S3, kinda cool having this again.