[2024-feb-29] Sad news: Eric Layton aka Nocturnal Slacker aka vtel57 passed away on Feb 26th, shortly after hospitalization. He was one of our Wiki's most prominent admins. He will be missed.
Action disabled: register

Welcome to the Slackware Documentation Project

Hibernation with LVM, LUKS and a Swapfile

With this How To you can use a swap file instead a swap partition as described here.

First create a swap file (you can choose another name and / or size if you want):

dd if=/dev/zero of=/swapfile bs=1M count=4096
mkswap /swapfile 

Activate the swap:

swapon /swapfile

Check if the swap file is recognized by the system:

cat /proc/swaps 
Filename                                Type            Size    Used    Priority
/swapfile                               file            4194300 0       -1

Add to the fstab

/swapfile        none             swap        defaults         0   0

For suspend/resume you need to append 2 kernel parameter in /etc/lilo.conf resume and resume_offset.

resume is the partition where the swap file is located (e.g /dev/sda, /dev/cryptslack/root) resume_offset is the beginning of the swap file on the resume partition, you can get the offset with:

sudo /sbin/filefrag -v /swapfile | head -n -3 | tail -n 1 | awk ' {print $3 }'

Your lilo entry should look like this:

# Append any additional kernel parameters:
 append="vt.default_utf8=1 resume=/dev/cryptslack/root resume_offset=1134591"

You need to patch the initrd to recognize the resume_offset parameter

init-swapfile.patch
--- init.orig   2012-12-01 14:03:39.344538490 +0100                                                                                                            
+++ init        2012-12-01 14:01:12.526373970 +0100                                                                                                            
@@ -69,6 +69,7 @@                                                                                                                                              
 LUKSDEV=$(cat /luksdev)                                                                                                                                       
 LUKSKEY=$(cat /lukskey)                                                                                                                                       
 RESUMEDEV=$(cat /resumedev)                                                                                                                                   
+RESOFFSET=$(cat /resoffset)                                                                                                                                   
 WAIT=$(cat /wait-for-root)                                                                                                                                    
 KEYMAP=$(cat /keymap)                                                                                                                                         
 INIT=/sbin/init                                                                                                                                               
@@ -269,18 +270,35 @@
     umount -l /mountkey
     rmdir /mountkey 2>/dev/null
   fi
-  
-  # Resume state from swap
-  if [ "$RESUMEDEV" != "" ]; then
-    if ls -l $RESUMEDEV | grep -q "^l" ; then
-      #RESUMEDEV=$(ls -l $RESUMEDEV | awk '{ print $NF }')
-      RESUMEDEV=$(readlink -f $RESUMEDEV)
-    fi
-    echo "Trying to resume from $RESUMEDEV"
-    RESMAJMIN=$(ls -l $RESUMEDEV | tr , : | awk '{ print $5$6 }')
-    echo $RESMAJMIN > /sys/power/resume
-  fi
-
+ 
+if [ "$RESUMEDEV" != "" ]; then
+       # be lvm aware
+        RESUMEDEV=$(readlink -f ${RESUMEDEV} | awk -F '/' '{ print $3 }')
+       if [ -r "/sys/class/block/${RESUMEDEV}/dev" ] ; then
+       # try sysfs 
+               read RESMAJMIN < "/sys/class/block/${RESUMEDEV}/dev"
+       elif [ -r "/proc/partitions" ] ; then
+       # otherwise run through /proc/partitions
+               while read m n b d jnk ; do
+                       if [ "$d" = "${RESUMEDEV}" ] ; then
+                               RESMAJMIN="$m:$n"
+                               break
+                       fi
+               done < "/proc/partitions"
+               fi
+       if [ -z "${RESMAJMIN}" ] ; then
+               # Device does not exist (not found in /proc/partitions)
+               exit 99
+       fi
+
+       if [ -n "${RESOFFSET}" ]; then
+                echo "Try resume from ${RESMAJMIN}:${RESOFFSET}"
+               echo "${RESMAJMIN}:${RESOFFSET}" > /sys/power/resume
+       else
+               echo "${RESMAJMIN}" > /sys/power/resume
+       fi
+fi
+ 
mkdir patched_initrd
cd patched_initrd
cp -r /boot/initrd-tree .
echo "1134591" > resoffset
patch < init-swapfile.patch

After successful patching, pack the initrd to /boot/initrd-swapfile.gz:

find . -print0 | cpio -ov -0 --format=newc | gzip -9 > /boot/initrd-swapfile.gz
I recommend to test this initrd first with another boot entry
image = /boot/vmlinuz
initrd = /boot/initrd-swapfile.gz
root = /dev/cryptslack/root
label = "Linux Swapfile"
read-only

Then you need to run lilo to save the changes

lilo

After a reboot you can suspend to your swap file as with your swap partition

You need the reboot, suspend also uses resume_offset to find the swap file

Sources

 howtos:slackware_admin:swapfile_hibernation ()