Integrate TuxOnIce into Ubuntu's hibernation process

Published by cybso on
This is a post from my original site, which was hosted by the former blog service of the University of Osnabrück. I have moved it to the new site for archiving. Pages linked in this article may no longer work today, and the blog comments under the article no longer exist. Opinions expressed in this article reflect the point of view of the time of publication and do not necessarily reflect my opinion today.

Warning: At the moment I can not recommend to use this script in conjunction with filewriter if you use a journaling filesystem for your root partition (ext3, reiser, ...). The reason is that when using filewriter the initramfs-script in /etc/initramfs-tools/scripts/local-premount/resume_tuxonice mounts this partition read-only to get the hibernation file's target. Unfortunately, the journal will be replayed in any case, so "mount -r /dev/hdX" does not mean "mount /dev/hdX, but don't make any changes on it". And this may result in a filesystem corruption because the resumed system things that these open transaction have not been handled yet. I'll do some changes to the scripts during the weekend, so please be patient of you want to "suspend to file". Yesterday, I described how to patch TuxOnIce-support into Ubuntu's kernel image. Today we will learn how to integrate this into Ubuntu's default hibernation framework, pm-hibernate. By doing this, you'll benefit from TuxOnIce' features without modifying your bootloader's configuration file and will be able to use your desktop's "Suspend to Disk"-command without changing any system file (because a customized system file might be overwritten on your next update). Furthermore, you will be able to combine suspend to disk with encrypted swap devices or (I prefer this) suspend to a file on your encrypted root partition.

Please note that the scripts I'll introduce are tested only by myself (yet), and they still lack of some features. I would be happy about every improvement. And of course I do not provide any warranty, you'll do this on your own risk. I think that the worst thing that might happen is that data on your root partition gets lost. But of course you're doing backups, don't you?

So, let's start. Oh, wait... did you ensure that you have a suitable backup? Ok. First I'll introduce what has to be done, and at the end I'll provide the scripts that implements this. Well, the first thing we have to do is to add resume support into Ubuntu's initramfs-Image. That is the file stored in /boot, starting with ' initrd.img' and ending with your kernel's version. If you're curious: it's a gzip'd cpio-archive, you can extract it using the following command:

$ mkdir -p initramfs
$ cd initramfs
$ gunzip -c /boot/initrd.img-2.6.27-7-tuxonice | cpio -vi

This file is made by ' update-initramfs', a command that creates a "mini-linux" containing some basic binaries, libraries and kernel modules. Furthermore, it executes hooks from /usr/share/initramfs-tools/hooks and from /etc/initramfs-tools/hooks, adds runtime configuration from /usr/share/initramfs-tools/conf.d and /etc/initramfs-tools/conf.d and some event scripts from /usr/share/initramfs-tools/scripts and /etc/initramfs-tools/scripts. We'll use all of the /etc-stuff.

Normally, when you boot your system, the following happens (extremely shortened): Before mounting the root partition, /usr/share/initramfs-tools/script/local will run all executables inside of scripts/local-top and scrips/local-premount (note that the /usr/share- and /etc-trees get merged in the resulting archive). scripts/local-top/cryptroot asks for passwords to decrypt any encrypted partition that needs to be mounted before the system starts, for example '/' and your swap partition if you're using swsusp. It ensures that you entered the correct password by checking the partitions filesystem (otherwise an "unkown fstype, bad superblock or wrong password"-error is shown). Next, scripts/local-premount/resume will check for a hibernation image in your swap partition. If any, it will start resuming this image by executing '/bin/resume', otherwise the system will continue booting.

So, we have a few problems if we want to integrate TuxOnIce-support into this process, and it will not become easier if we want to resume from an encrypted swap device. But for the moment let's assume that this isn't the case - your swap partition is not encrypted or you want to use TuxOnIce FileWriter feature. We need a replacement for script/local-premount/resume, and to prevent any delay in the boot process it would be nice to disable the original resume script. Because we may want to switch between both systems later, it's a bad idea to just overwrite it - instead, we will add an additional script named /etc/initramfs-tools/scripts/local-premount/tuxonice-resume and use a hook stored in /etc/initramfs-tools/hooks/tuxonice to disable classic swsusp if neccessary. This is done by unsetting the 'execute'-bit of this file.

Things will become worse when trying to use this in conjunction with an encrypted swap device. The 'cryptroot'-hook would add this device into it's list and ask for a password before booting, but if it contains an active hibernation image, 'fstype' will not recognize it and so crypttool will reject the password ("unkown fstype..."). So we could write a patch for this tool and wait for an official release, or just wrap arround it. The 'tuxonice'-hook will rename 'fstype' to 'fstype.orig' and replace it by a customized script. This executes the original binary, and if it fails to determine the filesystem, the wrapper will test for TuxOnIce. This is done by comparing offset 4086 of the input device to 0xEDC302E9 using "dd". If matching, the wrapper returns "TuxOnIce" as filetype and 'cryptroot' (in scripts/local-top, not in hooks) will accept it.

Ok, but we still have to hook into Ubuntu's hibernation system. This is done by a script placed in '/etc/pm/sleep.d/01tuxonice'. It checks for a valid image file (if using filewriter). A valid image has to start with "TuxOnIce", the rest doesn't matter. And it should be large enough to save the whole memory into it. For this reason, this script will create or enlarge the file to the size of your memory, determined by the 'MemTotal:'-line in /proc/meminfo (because of this the first hibernation process after installing this script, changing the hibernation file or enlarging your memory will take quite a while). Finally, it writes resume information to a temporary file (this is the content of /sys/power/tuxonice/resume after defining /sys/power/tuxonice/file/target - have a look at the original documentation for details). Suspending to swap is much easier: The swap device has to be written to /sys/power/tuxonice/resume. When resuming, /etc/pm/sleep.d/01tuxonice removes the temporary file (if any).

There are two additional scripts in /etc/acpi/suspend.d/01-tuxonice.sh and /etc/acpi/resume.d/01-tuxonice.sh. These are wrappers for the (depricated?) acpi hibernation framework which is used when you press the "sleep button" on your keyboard, for example.

So, to use this scripts, download https://cybso.de/assets/imported/stuff/tuxonice-ubuntu-initramfs.tar.gz (dead link) and extract it into your filesystem's root (or into any other directory if you only want to have a look at it). A configuration file will be overwritten, so it is a good idea to make a copy of it (even if you made a backup before - you did it, didn't you?):

$ cd ~
$ wget https://cybso.de/assets/imported/tuxonice-ubuntu-initramfs.tar.gz
$ cd /
$ sudo cp /etc/initramfs-tools/conf.d/resume /etc/initramfs-tools/conf.d/resume.orig
$ sudo tar xvzf ~/tuxonice-ubuntu-initramfs.tar.gz

Now, let's have a look at '/etc/initramfs-tools/conf.d/resume'. You will find three parameters:

RESUME_METHOD="tuxonice"
RESUME=file:/.hibernation-file
RESUME_INFO=/.tuxonice-resume.info

The first one (RESUME_METHOD) enables TOI-support. If set to any other value then "tuxonice", the classic swsusp method will be used. The second one is known from the original configuration file. In this example, it points to the file where the hibernation image should be stored. It doesn't matter on which partition or device it is stored, but it has to be on your root partition if you want to use encrypted devices. When using a swap device, omit the 'file:'-prefix. If it is an unencrypted swap device, you may prepend a 'swap:'-prefix, but this shouldn't be neccessary. The last one, RESUME_INFO (described as 'temporary file' before), will be used in conjunction with filewriter to save the hibernation file's offset before suspending. This is required because TuxOnIce will not mount your root device to get this location by itself - instead, we will have to mount it read-only, extract the resume information and unmount it again. For this reason, RESUME_INFO must be a file on your root partition!

At the first time, and everytime you make any changes to /etc/initramfs-tools/conf.d/resume, you have to rebuild your initrd. As mentioned before this is done by an update-script (I assume that you're running the patched kernel at the moment - if not, you should stop and reboot NOW!):

sudo update-initramfs -c -k $(uname -r)

If you modified /boot/grub/menu.lst for getting TuxOnIce support, it is a goog idea to revert this changes now.

That's it. If you hack 'sudo pm-hibernate' into your console, or use your desktop managers "Suspend to disk"-button, the system should hibernate and resume using TuxOnIce (the first suspend might take some time because the hibernation file will be created).

There are still some features missing, so if you want to help in development, have a look at the following issues: