How can I hibernate on Ubuntu 16.04?

Solution 1:

Hibernation using systemctl and getting it working in tough cases

For me, pm-hibernate always fails. After some tweaks, I was able to hibernate using the interface of systemd (init system in 16.04 and above). I also managed to get it working on 17.04 with a swap file. This case study may be useful for others with problems.

First try:

sudo systemctl hibernate

If that fails, begin troubleshooting: in the hibernate state (HTD or ACPI S4) the machine state is written to disk so that no power is needed to preserve it. The state is written either to a swap partition or to a swap file. Note: if using Btrfs DO NOT attempt to use a swap file as this may cause filesystem corruption

Your swap partition or swap file may need to be the same size as RAM to allow hibernation, but there is a good chance you will be able to hibernate if it is at least 2/5 the size of RAM, according to the Arch wiki page, so try other steps first before increasing swap size.

If your problem is that you get a clean boot instead of the expected resume, at a minimum you most likely need to set a boot parameter to find the disk image

Find your swap partition:

grep swap /etc/fstab

for me this returns (partial output)

# swap was on /dev/mmcblk0p3 during installation

where /dev/mmcblk0p3 is the partition to specify

Add a boot parameter:

sudoedit /etc/default/grub

To the line starting GRUB_CMDLINE_LINUX_DEFAULT add resume=/dev/YourSwapPartition to the section in quotes (replace with the the partition you identified earlier). Using my example:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=/dev/mmcblk0p3" 

Any time you change this file, you must run sudo update-grub or the changes will have no effect.

Now you need to reboot. Then you can try to hibernate, by issuing the command:

sudo systemctl hibernate

To resume, press the power button and the system will boot.

If you still have problems, start debugging.

I include my case below as an example, but detailed information on debugging S states can be found in this blog and also this one.

Set some more boot parameters to capture more information. Remove quiet and splash and add initcall_debug and no_console_suspend which will cause init system calls to be printed to the console so you can watch what is going wrong. I set this:

GRUB_CMDLINE_LINUX_DEFAULT="resume=/dev/mmcblk0p3 no_console_suspend initcall_debug"

Which helped me see what was going wrong on resume from hibernation. You can also try using dmesg.

In my case, after resume I lost WiFi, and the kernel clearly was upset as most commands (for example reading anything from /sys, reloading modules or any systemctl command) would not work - the process would appear to start and just hang (all this would be returned to normal after reboot of course). Watching the system very slowly shut down and reading all the debug messages, I noticed that there were a lot of problems with "brcm", so I guessed my Broadcom wireless driver module was to blame. Sure enough I adjusted my hibernation procedure to unload the module first:

sudo modprobe -r brcmfmac
sudo systemctl hibernate

on resume I reinsert the module

sudo modprobe brcmfmac

And everything worked perfectly. I also have to blacklist the btsdio module which seems to be incompatible with brcmfmac


Update: Hibernation using a swap file on 17.04.

Once again with help from the Arch wiki page and some additional tinkering, I managed to get hibernation to work on 17.04 with a swap file. This required an additional boot parameter, resume_offset=n where n is the first number under physical_offset in the output of sudo filefrag -v /swapfile:

$ sudo filefrag -v /swapfile
Filesystem type is: ef53
File size of /swapfile is 1425873920 (348114 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..   32767:      34816..     67583:  32768:            
   1:    32768..   63487:      67584..     98303:  30720:            
   .... 

Therefore, the additional boot parameter in my case is resume_offset=34816. You still need to set a boot parameter for the partition to resume from. This will be the root partition (or whatever partition your swap file is located on) My parameters are now:

GRUB_CMDLINE_LINUX_DEFAULT="no_console_suspend initcall_debug resume=/dev/mmcblk1p2 resume_offset=34816"

Where /dev/mmcblk1p2 is my root partition (yours is more likely to be something like /dev/sda2).

During resume I saw the image loading successfully, but in my case (just an example - YMMVAPD) then some more drivers (i2c_designware) threw some errors and I got a complete system freeze on resume. Hibernation works if I unload those modules in addition to brcmfmac, but the system quickly becomes unusable without those modules. I therefore made a sort of script to unload the buggy modules and immediately reinsert them on resume:

# remove buggy modules
modprobe -r brcmfmac i2c_designware_platform i2c_designware_core &&
# hibernate
echo disk > /sys/power/state
# reinsert
modprobe i2c_designware_core i2c_designware_platform brcmfmac

When I want to hibernate, I run sudo bash script. This works great.


TL;DR

Use systemd, set a boot parameter for resume from swap, identify buggy drivers and unload them before initiating hibernation. If the system can't work for long without those modules or you need to unload several, it may be easier to use a simple script to initiate hibernation.

Solution 2:

You can use

sudo pm-hibernate 

to check if hibernate works on your system (this will hibernate your computer).

If it does not work , check if your swap size is at least as large as your RAM.

To add the option to the settings menu, you can create a configuration file. Open a terminal window and run this command:

sudo nano /etc/polkit-1/localauthority/50-local.d/com.ubuntu.enable-hibernate.pkla

It opens nano with an empty file. Copy the lines below and paste them into the nano window.

[Re-enable hibernate by default in upower]
Identity=unix-user:*
Action=org.freedesktop.upower.hibernate
ResultActive=yes

[Re-enable hibernate by default in logind]
Identity=unix-user:*
Action=org.freedesktop.login1.hibernate;org.freedesktop.login1.handle-hibernate-key;org.freedesktop.login1;org.freedesktop.login1.hibernate-multiple-sessions;org.freedesktop.login1.hibernate-ignore-inhibit
ResultActive=yes

Then save the changes and close nano and reboot the system to make Hibernate available appear on "Power options".

Reference: How do I hibernate my computer? in the official documentation for Ubuntu 16.04.

Hope it works. This worked for me after trying all other options.

Solution 3:

I think, how to enable hibernate for 16.04 answer is known to all as described in the Ubuntu Wiki (See below if you need the steps). But The things that need checking isn't thorough I think. At least, that's what I found.

Things to check

From my own tests, I've at least found one extra check that you should perform. I haven't found about it anywhere in the Internet.

Here are some checkings -

  1. Check that you're not using any btrfs partitions. Yes. From my test, I found that if you have btrfs partitions, hibernate will not work. Removing or changing the partition type to ext4 didn't help me. I needed to remove the btrfs-tools package.

    sudo apt-get purge btrfs-tools
    

    You might want to check other new partition types which are not well tested. Without removing package, blacklisting the driver might also work, but I haven't tested that.

  2. Also you need to check that you have a swap partition large enough to hold the content of RAM. If your RAM is 4 GB, swap should be at least 4 GB large ( You should allocate few more MB to be safe).

Steps to enable hibernate

It involves these steps

  1. Create a file as root in /etc/polkit-1/localauthority/50-local.d/enable-hibernate.pkla

    sudo -i nano /etc/polkit-1/localauthority/50-local.d/enable-hibernate.pkla
    
  2. Put these contents on that file

    [Re-enable hibernate by default in upower]
    Identity=unix-user:*
    Action=org.freedesktop.upower.hibernate
    ResultActive=yes
    
    [Re-enable hibernate by default in logind]
    Identity=unix-user:*
    Action=org.freedesktop.login1.hibernate;org.freedesktop.login1.handle-hibernate-key;org.freedesktop.login1;org.freedesktop.login1.hibernate-multiple-sessions;org.freedesktop.login1.hibernate-ignore-inhibit
    ResultActive=yes
    
  3. Save the file by pressing Ctrl-O. Exit with Ctrl-X

  4. Restart the polkitd daemon

    sudo systemctl restart polkitd.service
    

It should enable hibernate.