Guide: Laptop Hybrid Suspend on Linux

keep-calm-low-battery-257x300One feature desktop Linux has been lacking out of the box is hybrid-suspend, supported as of Kernel versions 3.6+.

The following guide lets you suspend to both memory and disk, so you never lose your work if your battery is depleted while suspended. The workflow looks like this:

  • Suspend to RAM and create a hibernate image (for example, when you shut your lid)
  • If you resume with battery power – you resume from memory
  • If you run out of battery while suspended, use the hibernate image to resume

This allows you to never lose your work due to your battery going out.
Here’s how you set it up (example: Fedora 22+)

1) Tell Your Desktop Environment to let systemd handle Power Management
(run as normal user)

XFCE
Use the xconf-query command below to tell systemd to handle power management.

xfconf-query -c xfce4-power-manager -p \
/xfce4-power-manager/logind-handle-lid-switch -s true

GNOME
This should work as-is with logind.conf settings below.  I don’t run GNOME so this is untested – please comment if this doesn’t work and I’ll update the guide.

KDE/Plasma
You need to tell powerdevil to perform no action when the lid is closed.

powerdevil_kde_hybrid_suspend

After that you need to follow the instructions on comment #5 of this KDE bug report.

Other Windows Managers (Awesome, i3, etc)
This should work out of the box.

2) Make Systemd (logind) Handle Close Lid Events with Hybrid Suspend
(run as root)

Uncomment/Edit the following lines in /etc/systemd/logind.conf
(you need both due to BZ#1039364)

HandleLidSwitch=hybrid-sleep
HandleLidSwitchDocked=hybrid-sleep

3) Install Systemd target to Lock Screen on Resume
(run as root)

Since systemd is now handling pm-suspend events, it has no way of telling your respective screensaver to lock.  We need to utilize a systemd unit file to invoke screensaver on resume.  I am going to focus on xscreensaver here as that’s the default for XFCE but see the below notes on other desktop environments.

** GNOME USERS ** Skip this step and see the stack exchange thread on gnome-screensaver via dbus

** KDE USERS **  You can skip this step.

** NOTE ** Change to your non-root username below before pasting the second part.

myuser=username
cat >  /etc/systemd/system/screenlock.service << EOF
[Unit]
Description=Lock the screen on resume from suspend

[Service]
User=$myuser
Environment=DISPLAY=:0
ExecStart=/usr/bin/xscreensaver-command -lock

[Install]
WantedBy=hybrid-sleep.target
EOF

4) Start / Enable Systemd Lockscreen Service
(run as root)

systemctl restart systemd-logind
systemctl enable screenlock.service
systemctl start screenlock.service

Start the screenlock service, your screen will lock – unlock it once and off you go.

systemctl enable screenlock.service

5) Setup Kernel to use Swap Partition for Hibernate
(run as root)

5A) Obtain the UUID of your swap partition

** NOTE ** You need to take the output of blkid like below for the next step.

blkid | grep swap

Note your output:

/dev/mapper/fedora-swap: UUID="cc4ed223-58db-43b9-9dd4-34bfabd0043a" TYPE="swap" 

5B) Now set a temporary variable for swap UUID

swapuuid="cc4ed223-58db-43b9-9dd4-34bfabd0043a" && echo $swapuuid

5C) Add Resume line into Grub

This next command does a sed in-line edit on the GRUB_CMDLINE_LINUX_DEFAULT portion of grub.conf, use with care. We choose to append after “quiet” because everyone probably has that set.

cp /etc/default/grub /root/grub-backup && sed -i \
"s/quiet/quiet resume=\/dev\/disk\/by-uuid\/$swapuuid/" \
/etc/default/grub

5D) Regenerate your initrd so it contains resume= option

grub2-mkconfig -o /boot/grub2/grub.cfg

At this point you need to reboot to take effect, but everything should work.

Suspend when closing lid will take a few seconds longer than normal since you’re also copying a hibernate image but I think it’s well worth the price.

Is it Working?

If things are working correctly you should see both the lid sleep trigger via Systemd and PM utils saving your hibernated image.  On Fedora 22+ a simple journalctl -xr showed this activity.

I have not found a way to quickly test hybrid suspend resume from hibernation without depleting the battery to 1-2% and closing the lid.  Google Hangouts or similar activities always kills my battery quickly.  It does work for me and others however and saved my work a few times.

example.com systemd-logind[1078]: Hibernating and suspending...
example.com systemd-logind[1078]: Lid closed.
example.com kernel: PM: Wrote 2751856 kbytes in 4.02 seconds (684.54 MB/s)
example.com kernel: PM: Image saving done.
example.com kernel: PM: Image saving progress: 100%
example.com kernel: PM: Image saving progress:  90%
example.com kernel: PM: Image saving progress:  80%
example.com kernel: PM: Image saving progress:  70%
example.com kernel: PM: Image saving progress:  60%
example.com kernel: PM: Image saving progress:  50%
example.com kernel: PM: Image saving progress:  40%
example.com kernel: PM: Image saving progress:  30%
example.com kernel: PM: Image saving progress:  20%
example.com kernel: PM: Image saving progress:  10%
example.com kernel: PM: Image saving progress:   0%
example.com kernel: PM: Using 3 thread(s) for compression.
              : Compressing and saving image data (687964 pages)...

Black Screen on Hibernate Resume
Sometimes you’ll get what appears to be a black screen when your battery is depleted and you resume from an hibernate image.  Simply increase your screen brightness.  This might just be a bug and you can also use the following entry in /etc/default/grub for a permanent fix:

video.use_native_backlight=0

Using Lots of Memory prior to Hybrid Suspend
One limitation to hibernate is that you cannot be using more physical memory than the size allotted to your swap partition.  While this is rare (Swap is usually the amount of your memory or around 8GB) it can happen.

Note, this does not mean that you need a swap partition equal to your total memory, only that your active memory usage shouldn’t exceed your swap partition size.  This is usually rare in modern Linux operating systems.  Below you can find some instructions to work around this if you run into this issue.

Resizing Swap Partition
Here’s some generic steps to expand your swap partition, stealing storage from your /home.  Note: this will NOT work on XFS as there’s no way to shrink partitions, only grow them.

  • Reboot into runlevel 1
  • Unmount /home
  • Resize your /home partition
lvresize --resizefs --size SIZE /dev/fedora/home

Note: SIZE should probably be the current size minus 8GB or whatever you’d need to make swap match your system memory.

  •  Extend your swap partition
swapoff -a ; lvextend /dev/fedora/swap -l +100%FREE ; swapon -a

About Will Foster

hobo devop/sysadmin, all-around nice guy.
This entry was posted in open source, sysadmin and tagged , , , , , . Bookmark the permalink.

2 Responses to Guide: Laptop Hybrid Suspend on Linux

  1. Oliver says:

    Hey Will,

    thanks a lot for the guide. One quick question. What is the best way to verify that the setup works as expected (except suspending and leave the notebook for 1 week to get the battery empty :D). Is there any log files to see, or any files created (like the hybrid image) that can be checked?
    I am trying to implement the setup on RHEL 7.

    Cheers
    Oliver

    Liked by 1 person

    • Will Foster says:

      Howdy Oliver, you should see both hybrid suspend being called by the lid close action and Systemd firing off to do that. Next, you’ll see the actual hibernate image creation in the logs. Below is an example. I have not found a way to “test” it other than do some task like running bluejeans or hangouts (they seem to kill laptop battery) until around 1-2% then closing the lid. Good question, I’ll add it to the guide.

      (Lid Sleep Notification)

      example.com systemd-logind[1078]: Hibernating and suspending…
      example.com systemd-logind[1078]: Lid closed.

      (hybrid suspend being called)

      — Subject: Unit hybrid-sleep.target has begun shutting down
      — Defined-By: systemd
      — Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel

      (saving of image – viewable via journalctl -xr for example)

      example.com kernel: PM: Wrote 2751856 kbytes in 4.02 seconds (684.54 MB/s)
      example.com kernel: PM: Image saving done.
      example.com kernel: PM: Image saving progress: 100%
      example.com kernel: PM: Image saving progress: 90%
      example.com kernel: PM: Image saving progress: 80%
      example.com kernel: PM: Image saving progress: 70%
      example.com kernel: PM: Image saving progress: 60%
      example.com kernel: PM: Image saving progress: 50%
      example.com kernel: PM: Image saving progress: 40%
      example.com kernel: PM: Image saving progress: 30%
      example.com kernel: PM: Image saving progress: 20%
      example.com kernel: PM: Image saving progress: 10%
      example.com kernel: PM: Image saving progress: 0%
      example.com kernel: PM: Using 3 thread(s) for compression.
      PM: Compressing and saving image data (687964 pages)…

      Like

Have a Squat, Leave a Reply ..

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s