From 7bf236874292fd073c6bdd27f89c3d9e81a79cbc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 5 Jan 2007 16:36:28 -0800 Subject: [PATCH] [PATCH] swsusp: Do not fail if resume device is not set In the kernels later than 2.6.19 there is a regression that makes swsusp fail if the resume device is not explicitly specified. It can be fixed by adding an additional parameter to mm/swapfile.c:swap_type_of() allowing us to pass the (struct block_device *) corresponding to the first available swap back to the caller. Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/swap.h | 2 +- kernel/power/swap.c | 9 +++++---- kernel/power/user.c | 7 ++++--- mm/swapfile.c | 8 +++++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index add51cebc8d9..5423559a44a6 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -245,7 +245,7 @@ extern int swap_duplicate(swp_entry_t); extern int valid_swaphandles(swp_entry_t, unsigned long *); extern void swap_free(swp_entry_t); extern void free_swap_and_cache(swp_entry_t); -extern int swap_type_of(dev_t, sector_t); +extern int swap_type_of(dev_t, sector_t, struct block_device **); extern unsigned int count_swap_pages(int, int); extern sector_t map_swap_page(struct swap_info_struct *, pgoff_t); extern sector_t swapdev_block(int, pgoff_t); diff --git a/kernel/power/swap.c b/kernel/power/swap.c index f133d4a6d817..3581f8f86acd 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -165,14 +165,15 @@ static int swsusp_swap_check(void) /* This is called before saving image */ { int res; - res = swap_type_of(swsusp_resume_device, swsusp_resume_block); + res = swap_type_of(swsusp_resume_device, swsusp_resume_block, + &resume_bdev); if (res < 0) return res; root_swap = res; - resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_WRITE); - if (IS_ERR(resume_bdev)) - return PTR_ERR(resume_bdev); + res = blkdev_get(resume_bdev, FMODE_WRITE, O_RDWR); + if (res) + return res; res = set_blocksize(resume_bdev, PAGE_SIZE); if (res < 0) diff --git a/kernel/power/user.c b/kernel/power/user.c index 89443b85163b..f7b7a785a5c6 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -57,7 +57,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) { data->swap = swsusp_resume_device ? - swap_type_of(swsusp_resume_device, 0) : -1; + swap_type_of(swsusp_resume_device, 0, NULL) : -1; data->mode = O_RDONLY; } else { data->swap = -1; @@ -268,7 +268,8 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, * so we need to recode them */ if (old_decode_dev(arg)) { - data->swap = swap_type_of(old_decode_dev(arg), 0); + data->swap = swap_type_of(old_decode_dev(arg), + 0, NULL); if (data->swap < 0) error = -ENODEV; } else { @@ -365,7 +366,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, swdev = old_decode_dev(swap_area.dev); if (swdev) { offset = swap_area.offset; - data->swap = swap_type_of(swdev, offset); + data->swap = swap_type_of(swdev, offset, NULL); if (data->swap < 0) error = -ENODEV; } else { diff --git a/mm/swapfile.c b/mm/swapfile.c index b9fc0e5de6d5..a2d9bb4e80df 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -434,7 +434,7 @@ void 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) +int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) { struct block_device *bdev = NULL; int i; @@ -450,6 +450,9 @@ int swap_type_of(dev_t device, sector_t offset) continue; if (!bdev) { + if (bdev_p) + *bdev_p = sis->bdev; + spin_unlock(&swap_lock); return i; } @@ -459,6 +462,9 @@ int swap_type_of(dev_t device, sector_t offset) se = list_entry(sis->extent_list.next, struct swap_extent, list); if (se->start_block == offset) { + if (bdev_p) + *bdev_p = sis->bdev; + spin_unlock(&swap_lock); bdput(bdev); return i;