Linux laptop with encrypted disk and hibernation

Capturing the steps how I figured out hibernation on LUKS with swap file in Btrfs subvolume.

The Laptop already have WIN10 installed. I want to install Linux on encrypted partition and without touching WIN10 even it’s efi to have dual bootable system. Hence need to create separate /boot/efi to keep WIN10 boot loader separate.

  1. Disk partition

Using USB installer of Qounos release prepared following partitios

  • /boot/efi 512 MB - FAT32
  • Rest free space as single LUKS partition
  • Format LUKS with SSD friendly BTRFS file system
  1. Complete Installation adding / and /home as brtfs subvolume
 btrfs subvolume list /
ID 256 gen 1794 top level 5 path @
ID 257 gen 1794 top level 5 path @home

/etc/fstab

UUID=6BAE-9722                            /boot/efi      vfat    umask=0077 0 2
/dev/mapper/luks-82396eb2-fed3-4b13-8e27-10c92afd231a /              btrfs   subvol=/@,defaults 0 0
/dev/mapper/luks-82396eb2-fed3-4b13-8e27-10c92afd231a /home          btrfs   subvol=/@home,defaults 0 0
  1. Tested system after installation completion and Dual booting is working fine

  2. swap file preparation inside encrypted LUKS

Btrfs on Linux kernel after version 5.0 does support swap files.
Put swap file in a dedicated subvolume to avoid timeshift error:

Text file busy / btrfs returned an error: 256 / Failed to create snapshot

mount the top-level root btrfs filesystem, which always has id 5 [ref: swap-inside-subvolume]

mkdir /btrfs_pool
mount -o subvolid=5 /dev/mapper/cryptdata /btrfs_pool
ls /btrfs_pool
# @  @home

btrfs subvolume create /btrfs_pool/@swap
ls /btrfs_pool
# @  @home  @swap

truncate -s 0 /btrfs_pool/@swap/swapfile
chattr +C /btrfs_pool/@swap/swapfile
btrfs property set /btrfs_pool/@swap/swapfile compression none
fallocate -l 16G /btrfs_pool/@swap/swapfile
chmod 600 /btrfs_pool/@swap/swapfile
mkswap /btrfs_pool/@swap/swapfile
# Setting up swapspace version 1, size = 16 GiB 
# no label, UUID=23cd89op-c158-4126-8389-5d56c0965uUp
mkdir /btrfs_pool/@/swap

I have created 16 GB swapfile ( RAM x2) and in the last line created the folder /swap to mount @swap subvolume. Finally unmount the pool

umount /btrfs_pool

Now add swap into /etc/fstab. First mount subvolume, then swapfile

/dev/mapper/luks-82396eb2-fed3-4b13-8e27-10c92afd231a /swap btrfs   subvol=/@swap,compress=no 0 0
/swap/swapfile none swap defaults 0 0
  1. Install the hibernator binary and run to add necessary parameters to boot loader.
sudo pacman -S hibernator
sudo hibernator

Adding the necessary kernel parameters to your bootloaders
Generating grub configuration file ...
Found theme: /usr/share/grub/themes/manjaro/theme.txt
Found linux image: /boot/vmlinuz-5.15-x86_64
Found initrd image: /boot/amd-ucode.img /boot/initramfs-5.15-x86_64.img
Found initrd fallback image: /boot/initramfs-5.15-x86_64-fallback.img
Found linux image: /boot/vmlinuz-5.15-rt-x86_64
Found initrd image: /boot/amd-ucode.img /boot/initramfs-5.15-rt-x86_64.img
Found initrd fallback image: /boot/initramfs-5.15-rt-x86_64-fallback.img
Warning: os-prober will be executed to detect other bootable partitions.
Its output will be used to detect bootable binaries on them and create new boot entries.
Found Windows Boot Manager on /dev/nvme0n1p1@/efi/Microsoft/Boot/bootmgfw.efi
Adding boot menu entry for UEFI Firmware Settings ...
Detecting snapshots ...
Found snapshot: 2022-04-16 02:04:35 | timeshift-btrfs/snapshots/2022-04-16_02-04-35/@ | ondemand | N/A |
Found snapshot: 2022-04-16 00:45:18 | timeshift-btrfs/snapshots/2022-04-16_00-45-18/@ | ondemand | N/A |
Found snapshot: 2022-04-15 23:36:47 | timeshift-btrfs/snapshots/2022-04-15_23-36-47/@ | ondemand | N/A |
Found 3 snapshot(s)
Unmount /tmp/grub-btrfs.ztD4nAdvia .. Success
Found memtest86+ image: /boot/memtest86+/memtest.bin
done
Resume hook was already present
  1. Adding Kernel parameters for hibernation
    swap file requires resume=swap_device and resume_offset=swap_file_offset

To get resume_offset value we need to calculate ( PHYSICAL OFFSET / PAGESIZE ) ref: arch-hibernate

Download tool btrfs_map_physical.c and compile the tool to collect Physical offset

gcc -O2 -o btrfs_map_physical btrfs_map_physical.c

( Do not try to use the filefrag tool, on Btrfs the “physical” offset reported by filefrag is not the real physical offset on disk)

./btrfs_map_physical /swap/swapfile 
FILE OFFSET	FILE SIZE	EXTENT OFFSET	EXTENT TYPE	LOGICAL SIZE	LOGICAL OFFSET	PHYSICAL SIZE	DEVID	PHYSICAL OFFSET
0	4096	0	regular	268435456	50496294912	268435456	151578425344
4096	268431360	4096	prealloc	268435456	50496294912	268435456	1	51578425344
268435456	268435456	0	prealloc	268435456	50764730368	268435456	1	51846860800
536870912	268435456	0	prealloc	268435456	51033165824	268435456	1	52115296256
805306368	268435456	0	prealloc	268435456	57646301184	268435456	1	58728431616
1073741824	268435456	0	prealloc	268435456	92032466944	268435456	1	77008470016
1342177280	268435456	0	prealloc	268435456	92372205568	268435456	1	35472277504
1610612736	268435456	0	prealloc	268435456	92640641024	268435456	1	35740712960
1879048192	268435456	0	prealloc	268435456	92909076480	268435456	1	36009148416
2147483648	268435456	0	prealloc	268435456	93177511936	268435456	1	36277583872
2415919104	268435456	0	prealloc	268435456	93445947392	268435456	1	36546019328
2684354560	268435456	0	prealloc	268435456	93714382848	268435456	1	36814454784
2952790016	268435456	0	prealloc	268435456	93982818304	268435456	1	37082890240
3221225472	268435456	0	prealloc	268435456	94251253760	268435456	1	37351325696
3489660928	268435456	0	prealloc	268435456	94519689216	268435456	1	37619761152
3758096384	268435456	0	prealloc	268435456	94788124672	268435456	1	37888196608
4026531840	268435456	0	prealloc	268435456	95056560128	268435456	1	38156632064
4294967296	268435456	0	prealloc	268435456	95324995584	268435456	1	38425067520
4563402752	268435456	0	prealloc	268435456	95593431040	268435456	1	38693502976
4831838208	268435456	0	prealloc	268435456	95861866496	268435456	1	38961938432
5100273664	268435456	0	prealloc	268435456	96130301952	268435456	1	39230373888
5368709120	268435456	0	prealloc	268435456	96398737408	268435456	1	39498809344
5637144576	268435456	0	prealloc	268435456	96667172864	268435456	1	39767244800
5905580032	268435456	0	prealloc	268435456	96935608320	268435456	1	40035680256
6174015488	268435456	0	prealloc	268435456	97204043776	268435456	1	40304115712
6442450944	268435456	0	prealloc	268435456	97472479232	268435456	1	40572551168
6710886400	268435456	0	prealloc	268435456	97740914688	268435456	1	40840986624
6979321856	268435456	0	prealloc	268435456	98009350144	268435456	1	41109422080
7247757312	268435456	0	prealloc	268435456	98277785600	268435456	1	41377857536
7516192768	268435456	0	prealloc	268435456	98546221056	268435456	1	41646292992
7784628224	268435456	0	prealloc	268435456	98814656512	268435456	1	41914728448
8053063680	268435456	0	prealloc	268435456	99083091968	268435456	1	42183163904
8321499136	268435456	0	prealloc	268435456	99351527424	268435456	1	42451599360
8589934592	268435456	0	prealloc	268435456	99619962880	268435456	1	42720034816
8858370048	268435456	0	prealloc	268435456	99888398336	268435456	1	42988470272
9126805504	268435456	0	prealloc	268435456	100156833792	268435456	1	43256905728
9395240960	268435456	0	prealloc	268435456	100425269248	268435456	1	43525341184
9663676416	268435456	0	prealloc	268435456	100693704704	268435456	1	43793776640
9932111872	268435456	0	prealloc	268435456	100962140160	268435456	1	44062212096
10200547328	268435456	0	prealloc	268435456	101230575616	268435456	1	44330647552
10468982784	268435456	0	prealloc	268435456	101499011072	268435456	1	44599083008
10737418240	268435456	0	prealloc	268435456	101767446528	268435456	1	44867518464
11005853696	268435456	0	prealloc	268435456	102035881984	268435456	1	45135953920
11274289152	268435456	0	prealloc	268435456	102304317440	268435456	1	45404389376
11542724608	268435456	0	prealloc	268435456	102572752896	268435456	1	45672824832
11811160064	268435456	0	prealloc	268435456	102841188352	268435456	1	45941260288
12079595520	268435456	0	prealloc	268435456	103109623808	268435456	1	46209695744
12348030976	268435456	0	prealloc	268435456	103378059264	268435456	1	46478131200
12616466432	268435456	0	prealloc	268435456	103646494720	268435456	1	46746566656
12884901888	268435456	0	prealloc	268435456	103914930176	268435456	1	47015002112
13153337344	268435456	0	prealloc	268435456	104183365632	268435456	1	47283437568
13421772800	268435456	0	prealloc	268435456	104451801088	268435456	1	47551873024
13690208256	268435456	0	prealloc	268435456	104720236544	268435456	1	47820308480
13958643712	268435456	0	prealloc	268435456	104988672000	268435456	1	48088743936
14227079168	268435456	0	prealloc	268435456	105257107456	268435456	1	48357179392
14495514624	268435456	0	prealloc	268435456	105525542912	268435456	1	48625614848
14763950080	268435456	0	prealloc	268435456	105793978368	268435456	1	48894050304
15032385536	268435456	0	prealloc	268435456	106062413824	268435456	1	49162485760
15300820992	268435456	0	prealloc	268435456	106330849280	268435456	1	49430921216
15569256448	268435456	0	prealloc	268435456	106599284736	268435456	1	49699356672
15837691904	268435456	0	prealloc	268435456	106867720192	268435456	1	49967792128
16106127360	268435456	0	prealloc	268435456	107136155648	268435456	1	50236227584
16374562816	268435456	0	prealloc	268435456	107404591104	268435456	1	50504663040
16642998272	268435456	0	prealloc	268435456	107673026560	268435456	1	50773098496
16911433728	268435456	0	prealloc	268435456	107941462016	268435456	1	51041533952

Captured the first physical offset for the calculation. The PAGESIZE can be identified by

# getconf PAGESIZE
4096

Now modify the /etc/default/grub to add root , resume and resume_offset at GRUB_CMDLINE_LINUX_DEFAULT

GRUB_CMDLINE_LINUX_DEFAULT=“quiet cryptdevice=UUID=82396eb2-fed3-4b13-8e27-10c92afd231a:luks-82396eb2-fed3-4b13-8e27-10c92afd231a root=/dev/mapper/luks-82396eb2-fed3-4b13-8e27-10c92afd231a resume=/dev/mapper/luks-82396eb2-fed3-4b13-8e27-10c92afd231a resume_offset=12592389

apply the modification

sudo update-grub

and reboot to get the kernel parameters enabled.

  1. Finally the Hibernation

If everything goes fine you can now have the hibernation working. Check it by

sudo systemctl hibernate