PM: hibernate: align default resume swap with image-device checks
Subsystems (2)
PATCH 1/1 PM: hibernate: align default resume swap with image-device checks
snapshot_open(O_RDONLY) pins the configured default resume swap area for hibernation image writes, but it does not fully propagate that choice to the image-device checks used by the block layer.
In particular, snapshot_open() uses swsusp_resume_device without swsusp_resume_block when pinning the default resume swap area, and it leaves snapshot_state.dev unset even after the pin succeeds. As a result, the default resume swap selected at open time is not kept aligned with is_hibernate_resume_dev() and can still be rejected by the block layer in blkdev_write_iter() with -ETXTBSY until user space explicitly selects the same area via SNAPSHOT_SET_SWAP_AREA.
Use swsusp_resume_block when pinning the default resume swap area and record the device immediately after a successful pin so that the hibernation image-device bookkeeping matches the configured resume area. Also clear snapshot_state.dev on the open-time error path so it never advertises a session that failed to fully open.
uswsusp itself is not affected because it always calls SNAPSHOT_SET_SWAP_AREA right after open, which immediately overrides snapshot_state.dev and re-pins the swap area. The user-visible change is for minimal hibernation user space that relies on resume= and resume_offset= alone: such tools no longer have to restate the resume area via SNAPSHOT_SET_SWAP_AREA just to satisfy blkdev_write_iter()'s IS_SWAPFILE gate or to obtain SWP_HIBERNATION swapoff protection. This also matches the intent of the existing "The image device should be accessible" comment in snapshot_open(). For the configured default resume area, this gives snapshot_open() the same pin and recorded-device state that SNAPSHOT_SET_SWAP_AREA would establish for that same area, so user space relying on resume= and resume_offset= does not need a follow-up SNAPSHOT_SET_SWAP_AREA just to satisfy the IS_SWAPFILE gate and obtain swapoff protection.
---
Based on linux-next/master at commit e6efabc0afca ("Add linux-next specific files for 20260414").
Tested in QEMU: with swap on a block device pointed to by /sys/power/resume, opening /dev/snapshot O_RDONLY and then writing to the swap block device returned -ETXTBSY before this change and -ENOSPC (i.e. no longer rejected by the IS_SWAPFILE gate) after.
kernel/power/user.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
kernel/power/user.c +6 -2
@@ -69,9 +69,13 @@ static int snapshot_open(struct inode *inode, struct file *filp) data = &snapshot_state; filp->private_data = data;memset (&data->handle,0 ,sizeof (struct snapshot_handle )); + data->dev =0 ;if ((filp->f_flags &O_ACCMODE ) ==O_RDONLY ) {/* Hibernating. The image device should be accessible. */ - data->swap =pin_hibernation_swap_type (swsusp_resume_device,0 ); + data->swap =pin_hibernation_swap_type (swsusp_resume_device, + swsusp_resume_block); +if (data->swap >=0 ) + data->dev = swsusp_resume_device; data->mode =O_RDONLY ; data->free_bitmaps = false; error =pm_notifier_call_chain_robust (PM_HIBERNATION_PREPARE ,PM_POST_HIBERNATION );
@@ -92,13 +96,13 @@ static int snapshot_open(struct inode *inode, struct file *filp) }if (error) {unpin_hibernation_swap_type (data->swap); + data->dev =0 ;hibernate_release (); } data->frozen = false; data->ready = false; data->platform_support = false; - data->dev =0 ; Unlock:unlock_system_sleep (sleep_flags);
Signature · 1 line
2.43.0
On Wed, Apr 15, 2026 at 05:12:13PM +0900, DaeMyung Kang wrote:
Hello DaeMyung again :)
Quoted 33 lines
snapshot_open(O_RDONLY)pins the configured default resume swap area for hibernation image writes, but it does not fully propagate that choice to the image-device checks used by the block layer.In particular,
snapshot_open()usesswsusp_resume_devicewithoutswsusp_resume_blockwhen pinning the default resume swap area, and it leaves snapshot_state.dev unset even after the pin succeeds. As a result, the default resume swap selected at open time is not kept aligned withis_hibernate_resume_dev()and can still be rejected by the block layer inblkdev_write_iter()with-ETXTBSYuntil user space explicitly selects the same area viaSNAPSHOT_SET_SWAP_AREA.Use
swsusp_resume_blockwhen pinning the default resume swap area and record the device immediately after a successful pin so that the hibernation image-device bookkeeping matches the configured resume area. Also clear snapshot_state.dev on the open-time error path so it never advertises a session that failed to fully open.uswsusp itself is not affected because it always calls
SNAPSHOT_SET_SWAP_AREAright after open, which immediately overrides snapshot_state.dev and re-pins the swap area. The user-visible change is for minimal hibernation user space that relies on resume= and resume_offset= alone: such tools no longer have to restate the resume area viaSNAPSHOT_SET_SWAP_AREAjust to satisfy blkdev_write_iter()'sIS_SWAPFILEgate or to obtainSWP_HIBERNATIONswapoff protection. This also matches the intent of the existing "The image device should be accessible" comment insnapshot_open(). For the configured default resume area, this givessnapshot_open()the same pin and recorded-device state thatSNAPSHOT_SET_SWAP_AREAwould establish for that same area, so user space relying on resume= and resume_offset= does not need a follow-upSNAPSHOT_SET_SWAP_AREAjust to satisfy theIS_SWAPFILEgate and obtain swapoff protection.
Quoted 1 line
Signed-off-by DaeMyung Kang <[email protected]>
So, to summarize: if the resume area and offset are fully specified via
kernel parameters, it should work with hibernation image write properly with just snapshot_open() without needing an explicit ioctl call, right? And since uswsusp
hibernation tools currently use the ioctl, this hasn't been a visible
issue so far.
Quoted 16 lines
Based on linux-next/master at commit
e6efabc0afca("Add linux-next specific files for 20260414").Tested in QEMU: with swap on a block device pointed to by
/sys/power/resume, opening/dev/snapshotO_RDONLYand then writing to the swap block device returned-ETXTBSYbefore this change and-ENOSPC(i.e. no longer rejected by theIS_SWAPFILEgate) after.kernel/power/user.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)kernel/power/user.c +0
-0
kernel/power/user.c static int snapshot_open(struct inode *inode, struct file *filp) · line 76
Quoted 9 lines
kernel/power/user.c +3
-1@@ -69,9 +69,13 @@ static int snapshot_open(struct inode *inode, struct file *filp) data = &snapshot_state; filp->private_data = data;memset (&data->handle,0 ,sizeof (struct snapshot_handle )); + data->dev =0 ;if ((filp->f_flags &O_ACCMODE ) ==O_RDONLY ) {/* Hibernating. The image device should be accessible. */ - data->swap =pin_hibernation_swap_type (swsusp_resume_device,0 ); + data->swap =pin_hibernation_swap_type (swsusp_resume_device, + swsusp_resume_block);
I might miss this situation, just using tool as you explain it. (cuz it uses ioctl always internally).
Thank you for catching and addressing it.
For checking, it is side effect of my patch,
I check my patch and did some code archaeology to check the history, and it seems this behavior (on the snapshot_open handler) has been there since the beginning (around v2.6.20).
1. Passing 0 as the offset parameter
2. Not setting data->dev
Both seem to originate from:
commit 915bae9ebe41 ("[PATCH] swsusp: use partition device and offset to identify swap areas", Dec 6, 2006).
Shortly after, the SNAPSHOT_SET_SWAP_AREA ioctl support was added in commit 37b2ba12df88 ("[PATCH] swsusp: add ioctl for swap files support", Dec 6, 2006).
This ioctl patch sets the offset and dev from the user appropriately.
Maybe I am wrong or miss somthing. Please correct me or double-check.
If my understanding is correct, this patch looks like a valid improvement. It also seems to address an issue that has existed for quite some time.
However, I'm not 100% sure whether the original behavior was intentional, It would be great to get additional reviews from others.
Best regards,
Youngjun Park.