mm: split swap_type_of
authorChristoph Hellwig <hch@lst.de>
Mon, 21 Sep 2020 07:19:56 +0000 (09:19 +0200)
committerJens Axboe <axboe@kernel.dk>
Wed, 23 Sep 2020 16:43:19 +0000 (10:43 -0600)
swap_type_of is used for two entirely different purposes:

 (1) check what swap type a given device/offset corresponds to
 (2) find the first available swap device that can be written to

Mixing both in a single function creates an unreadable mess.  Create two
separate functions instead, and switch both to pass a dev_t instead of
a struct block_device to further simplify the code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
include/linux/swap.h
kernel/power/swap.c
kernel/power/user.c
mm/swapfile.c

index 6610469..4340a7b 100644 (file)
@@ -467,7 +467,8 @@ extern int swapcache_prepare(swp_entry_t);
 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 **);
+int swap_type_of(dev_t device, sector_t offset);
+int find_first_swap(dev_t *device);
 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);
index 01e2858..9d3ffbf 100644 (file)
@@ -335,12 +335,17 @@ static int swsusp_swap_check(void)
 {
        int res;
 
-       res = swap_type_of(swsusp_resume_device, swsusp_resume_block,
-                       &hib_resume_bdev);
+       if (swsusp_resume_device)
+               res = swap_type_of(swsusp_resume_device, swsusp_resume_block);
+       else
+               res = find_first_swap(&swsusp_resume_device);
        if (res < 0)
                return res;
-
        root_swap = res;
+
+       hib_resume_bdev = bdget(swsusp_resume_device);
+       if (!hib_resume_bdev)
+               return -ENOMEM;
        res = blkdev_get(hib_resume_bdev, FMODE_WRITE, NULL);
        if (res)
                return res;
@@ -349,12 +354,6 @@ static int swsusp_swap_check(void)
        if (res < 0)
                blkdev_put(hib_resume_bdev, FMODE_WRITE);
 
-       /*
-        * Update the resume device to the one actually used,
-        * so the test_resume mode can use it in case it is
-        * invoked from hibernate() to test the snapshot.
-        */
-       swsusp_resume_device = hib_resume_bdev->bd_dev;
        return res;
 }
 
index b581568..6510a8f 100644 (file)
@@ -69,8 +69,7 @@ static int snapshot_open(struct inode *inode, struct file *filp)
        memset(&data->handle, 0, sizeof(struct snapshot_handle));
        if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
                /* Hibernating.  The image device should be accessible. */
-               data->swap = swsusp_resume_device ?
-                       swap_type_of(swsusp_resume_device, 0, NULL) : -1;
+               data->swap = swap_type_of(swsusp_resume_device, 0);
                data->mode = O_RDONLY;
                data->free_bitmaps = false;
                error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls);
@@ -210,7 +209,6 @@ struct compat_resume_swap_area {
 static int snapshot_set_swap_area(struct snapshot_data *data,
                void __user *argp)
 {
-       struct block_device *bdev;
        sector_t offset;
        dev_t swdev;
 
@@ -237,16 +235,10 @@ static int snapshot_set_swap_area(struct snapshot_data *data,
         * User space encodes device types as two-byte values,
         * so we need to recode them
         */
-       if (!swdev) {
-               data->swap = -1;
-               return -EINVAL;
-       }
-       data->swap = swap_type_of(swdev, offset, &bdev);
+       data->swap = swap_type_of(swdev, offset);
        if (data->swap < 0)
-               return -ENODEV;
-
-       data->dev = bdev->bd_dev;
-       bdput(bdev);
+               return swdev ? -ENODEV : -EINVAL;
+       data->dev = swdev;
        return 0;
 }
 
index 7438c4a..b90f869 100644 (file)
@@ -1801,13 +1801,12 @@ int free_swap_and_cache(swp_entry_t entry)
  *
  * This is needed for the suspend to disk (aka swsusp).
  */
-int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
+int swap_type_of(dev_t device, sector_t offset)
 {
-       struct block_device *bdev = NULL;
        int type;
 
-       if (device)
-               bdev = bdget(device);
+       if (!device)
+               return -1;
 
        spin_lock(&swap_lock);
        for (type = 0; type < nr_swapfiles; type++) {
@@ -1816,30 +1815,34 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
                if (!(sis->flags & SWP_WRITEOK))
                        continue;
 
-               if (!bdev) {
-                       if (bdev_p)
-                               *bdev_p = bdgrab(sis->bdev);
-
-                       spin_unlock(&swap_lock);
-                       return type;
-               }
-               if (bdev == sis->bdev) {
+               if (device == sis->bdev->bd_dev) {
                        struct swap_extent *se = first_se(sis);
 
                        if (se->start_block == offset) {
-                               if (bdev_p)
-                                       *bdev_p = bdgrab(sis->bdev);
-
                                spin_unlock(&swap_lock);
-                               bdput(bdev);
                                return type;
                        }
                }
        }
        spin_unlock(&swap_lock);
-       if (bdev)
-               bdput(bdev);
+       return -ENODEV;
+}
 
+int find_first_swap(dev_t *device)
+{
+       int type;
+
+       spin_lock(&swap_lock);
+       for (type = 0; type < nr_swapfiles; type++) {
+               struct swap_info_struct *sis = swap_info[type];
+
+               if (!(sis->flags & SWP_WRITEOK))
+                       continue;
+               *device = sis->bdev->bd_dev;
+               spin_unlock(&swap_lock);
+               return type;
+       }
+       spin_unlock(&swap_lock);
        return -ENODEV;
 }