Comment 12 for bug 1864930

Revision history for this message
Marian Klein (sandokan9) wrote :

patch exist, please apply for ubuntu 20.04:

marian@kubuntu2004:~/kernelubuntu/linux$ git diff
diff --git a/include/linux/swap.h b/include/linux/swap.h
index de2c67a33b7e..da1dc5a338cc 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -456,6 +456,7 @@ extern void swap_free(swp_entry_t);
 extern void swapcache_free_entries(swp_entry_t *entries, int n);
 extern int free_swap_and_cache(swp_entry_t);
 extern int swap_type_of(dev_t, sector_t, struct block_device **);
+extern void swap_relockall(void);
 extern unsigned int count_swap_pages(int, int);
 extern sector_t map_swap_page(struct page *, struct block_device **);
 extern sector_t swapdev_block(int, pgoff_t);
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 77438954cc2b..bfef2097edaa 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -271,6 +271,8 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                        break;
                }
                error = hibernation_restore(data->platform_support);
+ if (!error)
+ swap_relockall();
                break;

        case SNAPSHOT_FREE:
@@ -372,10 +374,16 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                         */
                        swdev = new_decode_dev(swap_area.dev);
                        if (swdev) {
+ struct block_device *bd;
                                offset = swap_area.offset;
- data->swap = swap_type_of(swdev, offset, NULL);
+ data->swap = swap_type_of(swdev, offset, &bd);
                                if (data->swap < 0)
                                        error = -ENODEV;
+
+ inode_lock(bd->bd_inode);
+ bd->bd_inode->i_flags &= ~S_SWAPFILE;
+ inode_unlock(bd->bd_inode);
+ bdput(bd);
                        } else {
                                data->swap = -1;
                                error = -EINVAL;
diff --git a/mm/swapfile.c b/mm/swapfile.c
index dab43523afdd..c7c83d3a313b 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1799,6 +1799,32 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
        return -ENODEV;
 }

+/* Re-lock swap devices after resuming from userspace suspend. */
+void swap_relockall(void)
+{
+ int type;
+
+ spin_lock(&swap_lock);
+ for (type = 0; type < nr_swapfiles; type++) {
+ struct swap_info_struct *sis = swap_info[type];
+ struct block_device *bdev = bdgrab(sis->bdev);
+
+ /*
+ * uswsusp only knows how to suspend to block devices, so we
+ * can skip swap files.
+ */
+ if (!(sis->flags & SWP_WRITEOK) ||
+ !(sis->flags & SWP_BLKDEV))
+ continue;
+
+ inode_lock(bdev->bd_inode);
+ bdev->bd_inode->i_flags |= S_SWAPFILE;
+ inode_unlock(bdev->bd_inode);
+ bdput(bdev);
+ }
+ spin_unlock(&swap_lock);
+}
+
 /*
  * Get the (PAGE_SIZE) block corresponding to given offset on the swapdev
  * corresponding to given index in swap_info (swap type).