Sunday, November 11, 2007

How to enable 'hibernate' on Ubuntu

I recently installed Ubuntu 6.10 ("Edgy Eft") on my ancient Dell Precision 340. However, I could not 'hibernate' like I could under Windows. I did some research and here's what I did to fix my system.

1. Set correct 'swap' partition

Hibernating writes the current session to the swap partition. So, if our swap partition is not mapped correctly, Ubuntu will obviously have trouble. To diagnose this problem, type 'free' on the command line to see how much swap space we have:
$ free | grep Swap
Swap: 0 0 0
Here, the swap space is zero. One can usually enable a device for swap with the 'swapon' command, so I tried that:
$ swapon -a
swapon: cannot stat /dev/disk/by-uuid/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee: No such file or directory
The 'swapon' command looks at the '/etc/fstab' file to determine which UUID should be used for swap. Since there was a 'No such file' error, it would seem that there is an entry in '/etc/fstab' which points to a file that doesn't exist.

Lets test this theory. First, see what is listed as the 'swap' device:
$ cat /etc/fstab | grep swap
UUID=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeee none swap sw 0 0
Now, check the '/dev/disk/by-uuid/' directory to see if any such UUID exists:
$ ls -l /dev/disk/by-uuid/
total 0
lrwxrwxrwx 1 root root 07D2-0A18 -> ../../sda1
lrwxrwxrwx 1 root root 99d3e3b8-d10d-4ad0-a859-896a64126e4e -> ../../sda3
lrwxrwxrwx 1 root root b4bc91e8-f644-45b9-81d0-2884bb5638a2 -> ../../sda5
lrwxrwxrwx 1 root root E2A87FC6A87F97AD -> ../../sda2
There is no UUID corresponding to aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeee, so our hypothesis is correct.

To fix this problem, we just need to update the '/etc/fstab' file with a UUID that actually exists. But which one should we use? To answer this question, use the 'fdisk' command:
$ sudo fdisk -l | grep swap
/dev/sda5 4788 4865 626503+ 82 Linux swap / Solaris
It is sda5. Looking back in '/dev/disk/by-uuid/', we can see this disk has a UUID of b4bc91e8-f644-45b9-81d0-2884bb5638a2.

Now we have all the information we need to set the swap partition correctly. First, edit the '/etc/fstab' file so that it has the correct UUID:
$ sudo gedit /etc/fstab # Edit file and save.
$ cat /etc/fstab | grep swap
UUID=b4bc91e8-f644-45b9-81d0-2884bb5638a2 none swap sw 0 0
Now we should be able to use 'swapon' with no trouble
$ swapon -a
And finally, verify that we have nonzero swap space with 'free':
$ free | grep -E 'Mem|Swap'
Mem: 515500 319868 195632 0 4292 118724
Swap: 626492 0 626492
Note that the entry for 'Swap' is greater than 'Mem'. This is good -- the 'hibernate' operation will have enough disk space to store all of memory. If we had less, we would have to fix this before proceeding. (This did not happen to me.)

Restart and verify our fix worked. But do not attempt to hibernate yet! The 'resume' process after hibernating may possibly undo all the work we just did.

2. Fix 'resume' partition UUID

When our system resumes from hibernate, it needs to know which partition to load the image from. Ubuntu looks for this information in the '/etc/initramfs-tools/conf.d/resume' file:
$ cat /etc/initramfs-tools/conf.d/resume
As you can see, it is looking for the old (incorrect) UUID that it thought was the swap partition, so we need to fix this here too:
$ sudo gedit /etc/initramfs-tools/conf.d/resume # Edit file and save.
Finally, we need to update the intitrd with the new UUID:
$ sudo update-initramfs -u
Restart your machine, and then try to hibernate and resume.

At this point, everything may just work. For me though, it was not sufficient. My computer would hibernate and seem to resume without any errors, but it was very slow and the screen was not refreshing properly. After poking around on the web, I decided to intsall a more reliable 'userspace' version of the software suspend program.

3. Switch to Userspace Software Suspend

Userspace Software Suspend (µswsusp) is an alternate suspend program from the one shipped with the Ubuntu kernel. Let's see if it works on our system. First, download and install the program like this:
sudo apt-get install uswsusp
Then, test the hibernate function manually:
sudo s2disk
If the test is successful, we'll want to make this program the default for the 'hibernate' operation. This command will do the trick:
sudo dpkg-divert --rename --divert /usr/sbin/pmi-disabled /usr/sbin/pmi
Restart and test 'hibernate' operations.

Btw, this still may not work. If that is the case, you can type the following command to undo the Userspace Software Suspend installation:
sudo dpkg-divert --rename --remove /usr/sbin/pmi
sudo apt-get remove uswsusp

Yay! After following these steps, I have been able to 'hibernate' successfully many times.