1

I have a laptop & I run Arch Linux. My laptop has a spinning hard drive rather than an SSD, so I hate swap. However, I need one to hibernate, and I want my laptop to hibernate every time power key is pressed or battery runs low. My idea now is to have swapon just before systemd-hibernate.service starts. (Of course, would be nice to also swapoff just after awakening.)

For the purpose, I made a dev-sda7.swap unit. Its operation is straightforward:

[Unit]

Description=Hibernate swapon
DefaultDependencies=false
TimeoutStopSec=infinity

[Swap]
What=/dev/sda7

I hoped to tie it to either sleep.target, hibernate.target or systemd-hibernate.service to have it started just before hibernation and stopped just after. However, things didn't work out so smoothly. For now I have dev-sda7.swap stop if I add PartOf=sleep.target & I have it start just before systemd-hibernate.service if I add WantedBy=systemd-hibernate.service & Before=systemd-hibernate.service. This sounds like success, but it's not.

logind.conf specifies HandlePowerKey=hibernate and, as I understand, it invokes systemctl hibernate. (Maybe it's more complicated, I don't know.) systemctl hibernate however would not issue start systemd-hibernate.service unless an integrated swap check is passed, which is not going to happen until start systemd-hibernate.service is issued. I hope you can see the complication here.

I'd like to use the logic of systemd to have my swap started. So I gather I have to somehow remove the swap check from logind. Otherwise, maybe there is a way to run a script just before this check — a script that would swapon.

A dedicated /etc/udev/rules.d/99-lowbat.rules specifies an arbitrary command to run when power runs low, which can be systemctl start systemd-hibernate.service. I wonder if there's an udev rule that runs a command when power key is pressed. I can then do without logind altogether.

What can you advise me?

We had a conversation of some length on Arch Linux forum that helped establish the evidence but offered no solution.

1 Answers1

2

The systemctl swap verification can be disabled by setting SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1 for the systemd-logind service. This can be done like so:

# systemctl edit systemd-logind.service

[Service]
Environment=SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1

Now, in order to actually swapon/swapoff when needed, you can add this service:

# vim /etc/systemd/system/swap-to-hibernate.service

[Unit]
Description=Swapon/off when hibernating or resuming
DefaultDependencies=no
Before=systemd-hibernate.service systemd-hybrid-sleep.service
StopWhenUnneeded=yes
RefuseManualStart=yes
RefuseManualStop=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/swapon /dev/sda7    # <--- can be file, too
ExecStop=/usr/bin/swapoff /dev/sda7   

[Install]
RequiredBy=systemd-hibernate.service systemd-hybrid-sleep.service

Then just enable it via # systemctl enable swap-to-hibernate.service. You might have to reboot in order for the logind env to take effect, though (maybe # systemctl daemon-reexec && systemctl reload systemd-logind will suffice, I'm not sure).

For more info see this systemd pull request and this readme.

Also, make sure the swap kernel parameters are in order (aka resume and resume_offset).

matan129
  • 215
  • 3
  • 11