Skip to content

Commit 5904de0

Browse files
yu-chen-surfrafaeljw
authored andcommitted
PM: hibernate: Do not get block device exclusively in test_resume mode
The system refused to do a test_resume because it found that the swap device has already been taken by someone else. Specifically, the swsusp_check()->blkdev_get_by_dev(FMODE_EXCL) is supposed to do this check. Steps to reproduce: dd if=/dev/zero of=/swapfile bs=$(cat /proc/meminfo | awk '/MemTotal/ {print $2}') count=1024 conv=notrunc mkswap /swapfile swapon /swapfile swap-offset /swapfile echo 34816 > /sys/power/resume_offset echo test_resume > /sys/power/disk echo disk > /sys/power/state PM: Using 3 thread(s) for compression PM: Compressing and saving image data (293150 pages)... PM: Image saving progress: 0% PM: Image saving progress: 10% ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300) ata1.00: configured for UDMA/100 ata2: SATA link down (SStatus 0 SControl 300) ata5: SATA link down (SStatus 0 SControl 300) ata6: SATA link down (SStatus 0 SControl 300) ata3: SATA link down (SStatus 0 SControl 300) ata4: SATA link down (SStatus 0 SControl 300) PM: Image saving progress: 20% PM: Image saving progress: 30% PM: Image saving progress: 40% PM: Image saving progress: 50% pcieport 0000:00:02.5: pciehp: Slot(0-5): No device found PM: Image saving progress: 60% PM: Image saving progress: 70% PM: Image saving progress: 80% PM: Image saving progress: 90% PM: Image saving done PM: hibernation: Wrote 1172600 kbytes in 2.70 seconds (434.29 MB/s) PM: S| PM: hibernation: Basic memory bitmaps freed PM: Image not found (code -16) This is because when using the swapfile as the hibernation storage, the block device where the swapfile is located has already been mounted by the OS distribution(usually mounted as the rootfs). This is not an issue for normal hibernation, because software_resume()->swsusp_check() happens before the block device(rootfs) mount. But it is a problem for the test_resume mode. Because when test_resume happens, the block device has been mounted already. Thus remove the FMODE_EXCL for test_resume mode. This would not be a problem because in test_resume stage, the processes have already been frozen, and the race condition described in Commit 39fbef4 ("PM: hibernate: Get block device exclusively in swsusp_check()") is unlikely to happen. Fixes: 39fbef4 ("PM: hibernate: Get block device exclusively in swsusp_check()") Reported-by: Yifan Li <yifan2.li@intel.com> Suggested-by: Pavankumar Kondeti <quic_pkondeti@quicinc.com> Tested-by: Pavankumar Kondeti <quic_pkondeti@quicinc.com> Tested-by: Wendy Wang <wendy.wang@intel.com> Signed-off-by: Chen Yu <yu.c.chen@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 08169a1 commit 5904de0

2 files changed

Lines changed: 12 additions & 4 deletions

File tree

kernel/power/hibernate.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -688,18 +688,22 @@ static int load_image_and_restore(void)
688688
{
689689
int error;
690690
unsigned int flags;
691+
fmode_t mode = FMODE_READ;
692+
693+
if (snapshot_test)
694+
mode |= FMODE_EXCL;
691695

692696
pm_pr_dbg("Loading hibernation image.\n");
693697

694698
lock_device_hotplug();
695699
error = create_basic_memory_bitmaps();
696700
if (error) {
697-
swsusp_close(FMODE_READ | FMODE_EXCL);
701+
swsusp_close(mode);
698702
goto Unlock;
699703
}
700704

701705
error = swsusp_read(&flags);
702-
swsusp_close(FMODE_READ | FMODE_EXCL);
706+
swsusp_close(mode);
703707
if (!error)
704708
error = hibernation_restore(flags & SF_PLATFORM_MODE);
705709

kernel/power/swap.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,9 +1518,13 @@ int swsusp_check(void)
15181518
{
15191519
int error;
15201520
void *holder;
1521+
fmode_t mode = FMODE_READ;
1522+
1523+
if (snapshot_test)
1524+
mode |= FMODE_EXCL;
15211525

15221526
hib_resume_bdev = blkdev_get_by_dev(swsusp_resume_device,
1523-
FMODE_READ | FMODE_EXCL, &holder);
1527+
mode, &holder);
15241528
if (!IS_ERR(hib_resume_bdev)) {
15251529
set_blocksize(hib_resume_bdev, PAGE_SIZE);
15261530
clear_page(swsusp_header);
@@ -1547,7 +1551,7 @@ int swsusp_check(void)
15471551

15481552
put:
15491553
if (error)
1550-
blkdev_put(hib_resume_bdev, FMODE_READ | FMODE_EXCL);
1554+
blkdev_put(hib_resume_bdev, mode);
15511555
else
15521556
pr_debug("Image signature found, resuming\n");
15531557
} else {

0 commit comments

Comments
 (0)