mm: split swap_type_of

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>
This commit is contained in:
Christoph Hellwig 2020-09-21 09:19:56 +02:00 committed by Jens Axboe
parent bb3247a399
commit 21bd900572
4 changed files with 35 additions and 40 deletions

View File

@ -467,7 +467,8 @@ extern int swapcache_prepare(swp_entry_t);
extern void swap_free(swp_entry_t); extern void swap_free(swp_entry_t);
extern void swapcache_free_entries(swp_entry_t *entries, int n); extern void swapcache_free_entries(swp_entry_t *entries, int n);
extern int free_swap_and_cache(swp_entry_t); 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 unsigned int count_swap_pages(int, int);
extern sector_t map_swap_page(struct page *, struct block_device **); extern sector_t map_swap_page(struct page *, struct block_device **);
extern sector_t swapdev_block(int, pgoff_t); extern sector_t swapdev_block(int, pgoff_t);

View File

@ -335,12 +335,17 @@ static int swsusp_swap_check(void)
{ {
int res; int res;
res = swap_type_of(swsusp_resume_device, swsusp_resume_block, if (swsusp_resume_device)
&hib_resume_bdev); res = swap_type_of(swsusp_resume_device, swsusp_resume_block);
else
res = find_first_swap(&swsusp_resume_device);
if (res < 0) if (res < 0)
return res; return res;
root_swap = 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); res = blkdev_get(hib_resume_bdev, FMODE_WRITE, NULL);
if (res) if (res)
return res; return res;
@ -349,12 +354,6 @@ static int swsusp_swap_check(void)
if (res < 0) if (res < 0)
blkdev_put(hib_resume_bdev, FMODE_WRITE); 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; return res;
} }

View File

@ -69,8 +69,7 @@ static int snapshot_open(struct inode *inode, struct file *filp)
memset(&data->handle, 0, sizeof(struct snapshot_handle)); memset(&data->handle, 0, sizeof(struct snapshot_handle));
if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
/* Hibernating. The image device should be accessible. */ /* Hibernating. The image device should be accessible. */
data->swap = swsusp_resume_device ? data->swap = swap_type_of(swsusp_resume_device, 0);
swap_type_of(swsusp_resume_device, 0, NULL) : -1;
data->mode = O_RDONLY; data->mode = O_RDONLY;
data->free_bitmaps = false; data->free_bitmaps = false;
error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls); 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, static int snapshot_set_swap_area(struct snapshot_data *data,
void __user *argp) void __user *argp)
{ {
struct block_device *bdev;
sector_t offset; sector_t offset;
dev_t swdev; 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, * User space encodes device types as two-byte values,
* so we need to recode them * so we need to recode them
*/ */
if (!swdev) { data->swap = swap_type_of(swdev, offset);
data->swap = -1;
return -EINVAL;
}
data->swap = swap_type_of(swdev, offset, &bdev);
if (data->swap < 0) if (data->swap < 0)
return -ENODEV; return swdev ? -ENODEV : -EINVAL;
data->dev = swdev;
data->dev = bdev->bd_dev;
bdput(bdev);
return 0; return 0;
} }

View File

@ -1801,13 +1801,12 @@ int free_swap_and_cache(swp_entry_t entry)
* *
* This is needed for the suspend to disk (aka swsusp). * 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; int type;
if (device) if (!device)
bdev = bdget(device); return -1;
spin_lock(&swap_lock); spin_lock(&swap_lock);
for (type = 0; type < nr_swapfiles; type++) { 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)) if (!(sis->flags & SWP_WRITEOK))
continue; continue;
if (!bdev) { if (device == sis->bdev->bd_dev) {
if (bdev_p)
*bdev_p = bdgrab(sis->bdev);
spin_unlock(&swap_lock);
return type;
}
if (bdev == sis->bdev) {
struct swap_extent *se = first_se(sis); struct swap_extent *se = first_se(sis);
if (se->start_block == offset) { if (se->start_block == offset) {
if (bdev_p)
*bdev_p = bdgrab(sis->bdev);
spin_unlock(&swap_lock); spin_unlock(&swap_lock);
bdput(bdev);
return type; return type;
} }
} }
} }
spin_unlock(&swap_lock); spin_unlock(&swap_lock);
if (bdev) return -ENODEV;
bdput(bdev); }
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; return -ENODEV;
} }