Skip to main content
Topic: nmve root, suspend to disk and the "resume" hook (Read 333 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

nmve root, suspend to disk and the "resume" hook

Hi all,

I recently migrated my notebook (ThinkPad E480, but I'm pretty sure that doesn't matter) from a HD to a NVMe SSD as root. I created the necessary partitions and rsynced all data over. After that, I tweaked fstab and re-installed grub. So far so good, I could boot and all seemed to work.

But: Suspend to disk didn't work anymore. I then found that I forgot to also alter the resume= kernel parameter. However, even after that, I could not resume a suspended session.

After some research, I found that I had to activate the "resume" hook in /etc/mkinitcpio.conf. That sounded meaningful … after that, suspend to disk worked again.

But now, I wonder: Why did everything work with the default config, without that "resume" hook, as long as I used a normal HD, and now that I have a NVMe SSD, I need the "resume" hook?

Sorry if that's a silly question … I come from Gentoo, I never used an initrd before …

Thanks for all clarifiaction/explanation!

Re: nmve root, suspend to disk and the "resume" hook

Reply #1
Hi l3u!
While I'm not an Artix expert, my guess is that the new SSD uses a different kernel driver, so the resume= is not enough now and something needs to be managed through userspace. From the Arch wiki:
Quote
Adds lzo and lz4 kernel modules to allow resuming when using a hibernation image compression algorithm other than the compile-time default.
Though this is just a guess, someone please correct me if I'm wrong  :)
You can also try reading the hook script itself in /usr/lib/initcpio/hooks/resume
By the way, which init system are you using?

Re: nmve root, suspend to disk and the "resume" hook

Reply #2
I'm using OpenRC. However, I think the resume happens before the init system does something, no?

Well, a different driver would actually be an explanation. It's the type of SSD that shows up as /dev/nvme0n1, not as /dev/sda1.

Re: nmve root, suspend to disk and the "resume" hook

Reply #3
I found an interesting Reddit post:
Quote
So, I realized why hibernation works without the resume hook. It's because the kernel parameter `resume` is set as `resume=/dev/sda2`, so the kernel has a major and minor partition value (2:2 in my case). If I set it as `resume=UUID=dev_uuid`, hibernation no longer works and I have to add the resume hook to the HOOKS array.
...which seems to be exactly what the resume hook does based on its script:
Code: [Select]
read -r major minor < <(stat -Lc '0x%t 0x%T' "$resumedev")
printf '%d:%d' "$major" "$minor" >/sys/power/resume
I wanted to test different resume= parameters in a virtual machine, but couldn't figure out how to get hibernation working in qemu :(
How does you current resume= parameter look?
Do you remember which naming scheme you used for resume= on the HDD?

Re: nmve root, suspend to disk and the "resume" hook

Reply #4
With the normal HD, it was resume=/dev/sda2, now, I changed it to resume=/dev/nvme0n1p2.

But I also tried the resume=UUID=xyz parameter before activating the "resume" hook. Which did not make it work.

Quite interesting :-)

Re: nmve root, suspend to disk and the "resume" hook

Reply #5
Solved it!
Basically, hibernation comes down to the magic numbers in /sys/power/resume :
Quote
To hibernate right away, obtain the volume's major and minor device numbers from lsblk and echo them in format major:minor to /sys/power/resume
Digging more into magic numbers:
Quote
The Linux® kernel represents character and block devices as pairs of numbers <major>:<minor>.
Some major numbers are reserved for particular device drivers. Other major numbers are dynamically assigned to a device driver when Linux boots.
So, some magic numbers are static, and some are dynamic. Here is a list of reserved major numbers:
Quote
8 block      SCSI disk devices (0-15)
                  0 = /dev/sda          First SCSI disk whole disk
                 16 = /dev/sdb          Second SCSI disk whole disk
                 32 = /dev/sdc          Third SCSI disk whole disk
                    ...
                240 = /dev/sdp          Sixteenth SCSI disk whole disk
So, for HDDs the major number will always be 8, unless you go further /dev/sdp. Now, what about NVMe drives? It shows up as major number 259, so from the reserved numbers:
Quote
259 block      Block Extended Major
                  Used dynamically to hold additional partition minor
                  numbers and allow large numbers of partitions per device
...and there's no mention of NVMe. Which means that major number 259 is not always going to be an NVMe drive! Now, why is this important? Because this means that the kernel can't reconstruct the magic numbers from a simple resume=/dev/nvme0n1p2, and needs the script from the resume hook discussed before.
But since the number 8 is reserved for /dev/sdX, the kernel can reconstruct from resume=/dev/sdXY, placing the appropriate numbers into /sys/power/resume.

Also, I recently had an opportunity to test this with hardware. Installed Artix from the base ISO, placed resume=/dev/sda2 into GRUB_CMDLINE_LINUX_DEFAULT, updated GRUB, rebooted, ran loginctl hibernate, and... everything resumed perfectly, with 8:2 being in /sys/power/hibernate, no need for a resume hook!
Now, I'm not a kernel wizard, so feel free to correct me, but this explanation seems to be right :)
This was a very interesting and thought provoking question, thanks, l3u! ;)

P.S. If anyone's curious, the source code for reading the magic numbers can be found in <your_linux_source_dir>/kernel/power/hibernate.c around line 1185 (the maj, min variables should be there)