Skip to content

Fix hibernation on btrfs swapfiles with dm-crypt (systemd 256+)#5761

Open
Cliffback wants to merge 3 commits into
basecamp:devfrom
Cliffback:omarchy-hibernation
Open

Fix hibernation on btrfs swapfiles with dm-crypt (systemd 256+)#5761
Cliffback wants to merge 3 commits into
basecamp:devfrom
Cliffback:omarchy-hibernation

Conversation

@Cliffback
Copy link
Copy Markdown
Contributor

@Cliffback Cliffback commented May 11, 2026

Summary

  • Work around systemd 256+ being unable to resolve btrfs swapfiles on dm-crypt as valid hibernation devices, causing CanHibernate to return na and systemd-sleep to fail with "Stale file handle"
  • Add SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1 drop-ins for both systemd-logind and systemd-hibernate services
  • Detect and fix stale resume_offset when the swapfile has been recreated at a different physical location
  • Place the resume mkinitcpio hook before filesystems so the kernel can restore the hibernation image before root is mounted read-write

Problem

Since systemd 256, find_suitable_hibernation_device_full() tries to resolve the swapfile's backing block device by stat()'ing the file. On btrfs with dm-crypt, stat() returns an anonymous btrfs device ID (e.g. 0:39) that doesn't match the actual block device (253:0 for /dev/mapper/root). This causes:

  1. CanHibernate returning "na" — hibernate option not shown in menus
  2. systemd-sleep failing with "Failed to find location to hibernate to: Stale file handle" — even when manually triggered

Additionally, resume_offset can become stale if the swapfile is ever recreated (the physical offset changes but the kernel parameter isn't updated), causing silent resume failures on boot.

The previous approach of appending HOOKS+=(resume) via a separate omarchy_resume.conf placed the resume hook after filesystems and fsck, which is too late — the kernel returns PM: Image not found (code -22) because the root filesystem is already mounted read-write by that point.

Fix

The upstream-acknowledged workaround is SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1 (systemd#30083). This PR applies it to both services that perform the check, adds stale offset detection, and inserts the resume hook directly into omarchy_hooks.conf before filesystems (removing the legacy omarchy_resume.conf).

Changes

  • bin/omarchy-hibernation-setup: resolve resume device/offset upfront, add stale offset fix, add both systemd bypass drop-ins, insert resume hook before filesystems in omarchy_hooks.conf
  • bin/omarchy-hibernation-remove: clean up the new drop-ins on removal, remove resume hook from omarchy_hooks.conf
  • bin/omarchy-hibernation-available: check for resume hook in omarchy_hooks.conf instead of the legacy omarchy_resume.conf
  • migrations/1778497305.sh: apply all fixes to existing installs — move resume hook to correct position, add systemd bypass drop-ins, fix stale offset

Testing

Tested on ASUS ROG Flow Z13 (AMD, LUKS + btrfs, systemd 260.1-2, kernel 7.0.5-2-cachyos). Hibernation and resume both work correctly after the fix.

I have had massive problems with hibernation the last months, then got it working, and then broke again after an omarchy update. This have fixed the issues for me at least

systemd 256+ cannot resolve btrfs swapfiles on dm-crypt to their backing
block device, causing CanHibernate to return 'na' and systemd-sleep to
fail with 'Stale file handle'. Work around this with
SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK on both systemd-logind and
systemd-hibernate services.

Also detect and fix stale resume_offset when the swapfile has been
recreated at a different physical location on the btrfs filesystem.

Ref: systemd/systemd#30083
Copilot AI review requested due to automatic review settings May 11, 2026 13:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Omarchy’s hibernation tooling to work around systemd 256+ failing hibernation suitability checks on btrfs swapfiles backed by dm-crypt, and adds logic to detect/update stale resume_offset when a swapfile has been recreated.

Changes:

  • Add systemd drop-ins to set SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1 for both systemd-logind and systemd-hibernate.
  • Resolve resume device/offset earlier and update stale resume_offset when needed.
  • Introduce a migration to apply the above fixes to existing installations, and update the removal script to clean up new drop-ins.

Tip

If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

Reviewed changes

Copilot reviewed 1 out of 3 changed files in this pull request and generated 1 comment.

File Description
migrations/1778497305.sh Applies systemd hibernation bypass drop-ins and updates stale resume_offset on existing installs.
bin/omarchy-hibernation-setup Adds bypass drop-ins and stale resume_offset updating during setup.
bin/omarchy-hibernation-remove Removes the new bypass drop-ins during hibernation teardown.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread migrations/1778497305.sh
@Cliffback Cliffback marked this pull request as draft May 11, 2026 19:39
@Cliffback Cliffback marked this pull request as ready for review May 11, 2026 21:37
Copilot AI review requested due to automatic review settings May 11, 2026 21:37
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 4 changed files in this pull request and generated 1 comment.

Comment thread migrations/1778497305.sh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants