PM / Hibernate: Group swap ops

Move all the swap processing into one function. It will make swap
calls from a non-swap code easier.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
This commit is contained in:
Jiri Slaby 2010-05-01 23:54:02 +02:00 committed by Rafael J. Wysocki
parent 51fb352b2c
commit 6f612af578

View File

@ -208,9 +208,10 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags)
/** /**
* swsusp_swap_check - check if the resume device is a swap device * swsusp_swap_check - check if the resume device is a swap device
* and get its index (if so) * and get its index (if so)
*
* This is called before saving image
*/ */
static int swsusp_swap_check(void)
static int swsusp_swap_check(void) /* This is called before saving image */
{ {
int res; int res;
@ -269,17 +270,33 @@ static void release_swap_writer(struct swap_map_handle *handle)
static int get_swap_writer(struct swap_map_handle *handle) static int get_swap_writer(struct swap_map_handle *handle)
{ {
int ret;
ret = swsusp_swap_check();
if (ret) {
if (ret != -ENOSPC)
printk(KERN_ERR "PM: Cannot find swap device, try "
"swapon -a.\n");
return ret;
}
handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL); handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL);
if (!handle->cur) if (!handle->cur) {
return -ENOMEM; ret = -ENOMEM;
goto err_close;
}
handle->cur_swap = alloc_swapdev_block(root_swap); handle->cur_swap = alloc_swapdev_block(root_swap);
if (!handle->cur_swap) { if (!handle->cur_swap) {
release_swap_writer(handle); ret = -ENOSPC;
return -ENOSPC; goto err_rel;
} }
handle->k = 0; handle->k = 0;
handle->first_sector = handle->cur_swap; handle->first_sector = handle->cur_swap;
return 0; return 0;
err_rel:
release_swap_writer(handle);
err_close:
swsusp_close(FMODE_WRITE);
return ret;
} }
static int swap_write_page(struct swap_map_handle *handle, void *buf, static int swap_write_page(struct swap_map_handle *handle, void *buf,
@ -322,6 +339,24 @@ static int flush_swap_writer(struct swap_map_handle *handle)
return -EINVAL; return -EINVAL;
} }
static int swap_writer_finish(struct swap_map_handle *handle,
unsigned int flags, int error)
{
if (!error) {
flush_swap_writer(handle);
printk(KERN_INFO "PM: S");
error = mark_swapfiles(handle, flags);
printk("|\n");
}
if (error)
free_all_swap_pages(root_swap);
release_swap_writer(handle);
swsusp_close(FMODE_WRITE);
return error;
}
/** /**
* save_image - save the suspend image data * save_image - save the suspend image data
*/ */
@ -399,48 +434,34 @@ int swsusp_write(unsigned int flags)
struct swap_map_handle handle; struct swap_map_handle handle;
struct snapshot_handle snapshot; struct snapshot_handle snapshot;
struct swsusp_info *header; struct swsusp_info *header;
unsigned long pages;
int error; int error;
error = swsusp_swap_check(); pages = snapshot_get_image_size();
error = get_swap_writer(&handle);
if (error) { if (error) {
printk(KERN_ERR "PM: Cannot find swap device, try " printk(KERN_ERR "PM: Cannot get swap writer\n");
"swapon -a.\n");
return error; return error;
} }
if (!enough_swap(pages)) {
printk(KERN_ERR "PM: Not enough free swap\n");
error = -ENOSPC;
goto out_finish;
}
memset(&snapshot, 0, sizeof(struct snapshot_handle)); memset(&snapshot, 0, sizeof(struct snapshot_handle));
error = snapshot_read_next(&snapshot); error = snapshot_read_next(&snapshot);
if (error < PAGE_SIZE) { if (error < PAGE_SIZE) {
if (error >= 0) if (error >= 0)
error = -EFAULT; error = -EFAULT;
goto out; goto out_finish;
} }
header = (struct swsusp_info *)data_of(snapshot); header = (struct swsusp_info *)data_of(snapshot);
if (!enough_swap(header->pages)) { error = swap_write_page(&handle, header, NULL);
printk(KERN_ERR "PM: Not enough free swap\n"); if (!error)
error = -ENOSPC; error = save_image(&handle, &snapshot, pages - 1);
goto out; out_finish:
} error = swap_writer_finish(&handle, flags, error);
error = get_swap_writer(&handle);
if (!error) {
error = swap_write_page(&handle, header, NULL);
if (!error)
error = save_image(&handle, &snapshot,
header->pages - 1);
if (!error) {
flush_swap_writer(&handle);
printk(KERN_INFO "PM: S");
error = mark_swapfiles(&handle, flags);
printk("|\n");
}
}
if (error)
free_all_swap_pages(root_swap);
release_swap_writer(&handle);
out:
swsusp_close(FMODE_WRITE);
return error; return error;
} }
@ -456,18 +477,21 @@ static void release_swap_reader(struct swap_map_handle *handle)
handle->cur = NULL; handle->cur = NULL;
} }
static int get_swap_reader(struct swap_map_handle *handle, sector_t start) static int get_swap_reader(struct swap_map_handle *handle,
unsigned int *flags_p)
{ {
int error; int error;
if (!start) *flags_p = swsusp_header->flags;
if (!swsusp_header->image) /* how can this happen? */
return -EINVAL; return -EINVAL;
handle->cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH); handle->cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH);
if (!handle->cur) if (!handle->cur)
return -ENOMEM; return -ENOMEM;
error = hib_bio_read_page(start, handle->cur, NULL); error = hib_bio_read_page(swsusp_header->image, handle->cur, NULL);
if (error) { if (error) {
release_swap_reader(handle); release_swap_reader(handle);
return error; return error;
@ -502,6 +526,13 @@ static int swap_read_page(struct swap_map_handle *handle, void *buf,
return error; return error;
} }
static int swap_reader_finish(struct swap_map_handle *handle)
{
release_swap_reader(handle);
return 0;
}
/** /**
* load_image - load the image using the swap map handle * load_image - load the image using the swap map handle
* @handle and the snapshot handle @snapshot * @handle and the snapshot handle @snapshot
@ -571,20 +602,20 @@ int swsusp_read(unsigned int *flags_p)
struct snapshot_handle snapshot; struct snapshot_handle snapshot;
struct swsusp_info *header; struct swsusp_info *header;
*flags_p = swsusp_header->flags;
memset(&snapshot, 0, sizeof(struct snapshot_handle)); memset(&snapshot, 0, sizeof(struct snapshot_handle));
error = snapshot_write_next(&snapshot); error = snapshot_write_next(&snapshot);
if (error < PAGE_SIZE) if (error < PAGE_SIZE)
return error < 0 ? error : -EFAULT; return error < 0 ? error : -EFAULT;
header = (struct swsusp_info *)data_of(snapshot); header = (struct swsusp_info *)data_of(snapshot);
error = get_swap_reader(&handle, swsusp_header->image); error = get_swap_reader(&handle, flags_p);
if (error)
goto end;
if (!error) if (!error)
error = swap_read_page(&handle, header, NULL); error = swap_read_page(&handle, header, NULL);
if (!error) if (!error)
error = load_image(&handle, &snapshot, header->pages - 1); error = load_image(&handle, &snapshot, header->pages - 1);
release_swap_reader(&handle); swap_reader_finish(&handle);
end:
if (!error) if (!error)
pr_debug("PM: Image successfully loaded\n"); pr_debug("PM: Image successfully loaded\n");
else else