Awesome FOSS Logo
Discover awesome open source software
Launched 🚀🧑‍🚀

Arch Adventures: Hibernating to swap file

Categories
arch-linux-logo

Welcome to first (of hopefully many) entries about my adventures using Arch Linux, which will most likely consist of me breaking things, then looking at documentation, then reading guides, then fixing the things I broke. :)

Lots of things happened today (they’re going to be subjects of other blog posts), but one thing I just got through doing was creating a swap file for suspend-to-disk (hibernate) to use.

Long story short, my phone died, and inbetween getting getting another one, my new laptop (which I like a lot) is going to be the only way I can keep in contact with people. To maximize battery life, it has recently become imperative that the hiberation feature works (which it didn’t before, but I just ignored).

Unfortunately, when I formatted the hard drive of this computer I did not include a swap partition (some guides I read seemed inconclusive on whether you really needed one nowadays) — turns out I did, but not for the reasons I thought. While I could have booted to the Arch installation media and tried to resize come partitions, I came across the possibility of using a swap file on disk instead of creating a dedicated swap partition. Here’s what I ended up doing to make it work:

1. Create an appropriately sized swap file

The general consensus (from random posts on the internet) seems to be that RAM+2GB is a good size for most swap files, if you’re going to be suspending to disk. I also found this excellent Ubuntu SWAP FAQ. Since my laptop has 8GB of RAM, I decided to make a 10GB swap file.

fallocate -l 512M /swapfile

# Set the right permissions (a world-readable swap file is a huge local vulnerability)
chmod 600 /swapfile

After creating the correctly sized file, format it to swap:
mkswap /swapfile

# Activate the swap file:
swapon /swapfile
 
# Finally, edit fstab to add an entry for the swap file:
# in /etc/fstab (one line):
# /swapfile none swap defaults 0 0

I highly recommend reading the Arch guide to creating the swap file, rather than just doing what is written above

2. Ensure that your kernel supports resuming (or enable it)

For me, this meant editing /etc/mkinitcpio.conf and making sure that “resume” was in the HOOKS array. The excellent Arch guide on hibernation specified that it needed to come after udev, and before autodetect.

3. Add kernel configuration to specify the drive the swap file is on, and the offset to the swap file

I don’t use grub, but instead use the EFI loader. This meant that I needed to modify /boot/loader/entries/arch.conf directly, and edit a line to look like this:

options	root=/dev/sda2 resume=/dev/sda2 resume_offset=567296 rw

resume= tells the kernel which hard drive the kernel file is on.

Not sure which hard drive your kernel file is on? Run lsblk and it should list it for you. I only have two partitions (one for boot, one for everything else), sda1 and sda2 respectively, so clearly swap file was on sda2.

resume_offset= tells the kernel how far into that drive the swap file is (where the swap file begins). To get this:

filefrag -v /swapfile

Again, I highly recommend you read the Arch guide instead of just copying what’s here (things might change).

That command assumes your swapfile is stored at /swapfile, and the value you need is physical_offset number (the second one that seems to be under that column).

For example if the output was:

Filesystem type is: ef53
File size of /swapfile is 4294967296 (1048576 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..       0:      38912..     38912:      1:            
   1:        1..   22527:      38913..     61439:  22527:             unwritten
   2:    22528..   53247:     899072..    929791:  30720:      61440: unwritten

The value you need would be 38912

After adding the kernel hook and the configuration, you need to rebuild the kernel using the mkinitcpio command:

mkinitcpio -c /etc/path/to/your/mkinitcpio.conf

That command does a dry run. If it succeeds and everything seems fine, you should use that configuration to generate an actual initramfs image.

MAKE SURE TO MAKE A BACKUP OF YOUR INITRAMFS IMAGE, JUST IN CASE.

My initramfs image is at /boot/initramfs-linux.img (I probably should have actually changed the linux preset for this… rather than using the /etc/mkinitcpio.conf I already had) — so I actually just generated the image straight there.

3. Reboot

If everything went well, then you can reboot, and hibernate will work! If things went wrong, remember that you can always boot from the installation media (CD/USB), and go through the Arch beginners guide to rebuild things. All your data will still be available (obviously, as messing up your kernel doesn’t delete all your data), so calm down, and try to revert.

This was a thoroughly fun/interesting ride, and also taught me quite a bit, and now I have a properly hibernating computer!