Commit 0fbeb5a4 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Linus Torvalds

[PATCH] swsusp: rework swsusp_suspend

This patch makes only the functions in swsusp.c call functions in snapshot.c
and not both ways.  It also moves the check for available swap out of
swsusp_suspend() which is necessary for separating the swap-handling functions
in swsusp from the core code.
Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Cc: Pavel Machek <pavel@ucw.cz>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ed14b527
...@@ -65,10 +65,8 @@ extern suspend_pagedir_t *pagedir_save; ...@@ -65,10 +65,8 @@ extern suspend_pagedir_t *pagedir_save;
extern asmlinkage int swsusp_arch_suspend(void); extern asmlinkage int swsusp_arch_suspend(void);
extern asmlinkage int swsusp_arch_resume(void); extern asmlinkage int swsusp_arch_resume(void);
extern int restore_highmem(void);
extern void free_pagedir(struct pbe *pblist); extern void free_pagedir(struct pbe *pblist);
extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed); extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed);
extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages); extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages);
extern void swsusp_free(void); extern void swsusp_free(void);
extern int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed); extern int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed);
extern int enough_swap(unsigned nr_pages);
...@@ -88,8 +88,7 @@ static int save_highmem_zone(struct zone *zone) ...@@ -88,8 +88,7 @@ static int save_highmem_zone(struct zone *zone)
return 0; return 0;
} }
int save_highmem(void)
static int save_highmem(void)
{ {
struct zone *zone; struct zone *zone;
int res = 0; int res = 0;
...@@ -120,11 +119,7 @@ int restore_highmem(void) ...@@ -120,11 +119,7 @@ int restore_highmem(void)
} }
return 0; return 0;
} }
#else #endif
static int save_highmem(void) { return 0; }
int restore_highmem(void) { return 0; }
#endif /* CONFIG_HIGHMEM */
static int pfn_is_nosave(unsigned long pfn) static int pfn_is_nosave(unsigned long pfn)
{ {
...@@ -416,11 +411,6 @@ asmlinkage int swsusp_save(void) ...@@ -416,11 +411,6 @@ asmlinkage int swsusp_save(void)
unsigned int nr_pages; unsigned int nr_pages;
pr_debug("swsusp: critical section: \n"); pr_debug("swsusp: critical section: \n");
if (save_highmem()) {
printk(KERN_CRIT "swsusp: Not enough free pages for highmem\n");
restore_highmem();
return -ENOMEM;
}
drain_local_pages(); drain_local_pages();
nr_pages = count_data_pages(); nr_pages = count_data_pages();
...@@ -440,11 +430,6 @@ asmlinkage int swsusp_save(void) ...@@ -440,11 +430,6 @@ asmlinkage int swsusp_save(void)
return -ENOMEM; return -ENOMEM;
} }
if (!enough_swap(nr_pages)) {
printk(KERN_ERR "swsusp: Not enough free swap\n");
return -ENOSPC;
}
pagedir_nosave = swsusp_alloc(nr_pages); pagedir_nosave = swsusp_alloc(nr_pages);
if (!pagedir_nosave) if (!pagedir_nosave)
return -ENOMEM; return -ENOMEM;
......
...@@ -73,6 +73,14 @@ ...@@ -73,6 +73,14 @@
#include "power.h" #include "power.h"
#ifdef CONFIG_HIGHMEM
int save_highmem(void);
int restore_highmem(void);
#else
static int save_highmem(void) { return 0; }
static int restore_highmem(void) { return 0; }
#endif
#define CIPHER "aes" #define CIPHER "aes"
#define MAXKEY 32 #define MAXKEY 32
#define MAXIV 32 #define MAXIV 32
...@@ -499,6 +507,26 @@ static int write_pagedir(void) ...@@ -499,6 +507,26 @@ static int write_pagedir(void)
return error; return error;
} }
/**
* enough_swap - Make sure we have enough swap to save the image.
*
* Returns TRUE or FALSE after checking the total amount of swap
* space avaiable.
*
* FIXME: si_swapinfo(&i) returns all swap devices information.
* We should only consider resume_device.
*/
static int enough_swap(unsigned int nr_pages)
{
struct sysinfo i;
si_swapinfo(&i);
pr_debug("swsusp: available swap: %lu pages\n", i.freeswap);
return i.freeswap > (nr_pages + PAGES_FOR_IO +
(nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
}
/** /**
* write_suspend_image - Write entire image and metadata. * write_suspend_image - Write entire image and metadata.
* *
...@@ -507,6 +535,11 @@ static int write_suspend_image(void) ...@@ -507,6 +535,11 @@ static int write_suspend_image(void)
{ {
int error; int error;
if (!enough_swap(nr_copy_pages)) {
printk(KERN_ERR "swsusp: Not enough free swap\n");
return -ENOSPC;
}
init_header(); init_header();
if ((error = data_write())) if ((error = data_write()))
goto FreeData; goto FreeData;
...@@ -526,27 +559,6 @@ static int write_suspend_image(void) ...@@ -526,27 +559,6 @@ static int write_suspend_image(void)
goto Done; goto Done;
} }
/**
* enough_swap - Make sure we have enough swap to save the image.
*
* Returns TRUE or FALSE after checking the total amount of swap
* space avaiable.
*
* FIXME: si_swapinfo(&i) returns all swap devices information.
* We should only consider resume_device.
*/
int enough_swap(unsigned int nr_pages)
{
struct sysinfo i;
si_swapinfo(&i);
pr_debug("swsusp: available swap: %lu pages\n", i.freeswap);
return i.freeswap > (nr_pages + PAGES_FOR_IO +
(nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
}
/* It is important _NOT_ to umount filesystems at this point. We want /* It is important _NOT_ to umount filesystems at this point. We want
* them synced (in case something goes wrong) but we DO not want to mark * them synced (in case something goes wrong) but we DO not want to mark
* filesystem clean: it is not. (And it does not matter, if we resume * filesystem clean: it is not. (And it does not matter, if we resume
...@@ -556,12 +568,15 @@ int swsusp_write(void) ...@@ -556,12 +568,15 @@ int swsusp_write(void)
{ {
int error; int error;
if ((error = swsusp_swap_check())) {
printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n");
return error;
}
lock_swapdevices(); lock_swapdevices();
error = write_suspend_image(); error = write_suspend_image();
/* This will unlock ignored swap devices since writing is finished */ /* This will unlock ignored swap devices since writing is finished */
lock_swapdevices(); lock_swapdevices();
return error; return error;
} }
...@@ -569,6 +584,7 @@ int swsusp_write(void) ...@@ -569,6 +584,7 @@ int swsusp_write(void)
int swsusp_suspend(void) int swsusp_suspend(void)
{ {
int error; int error;
if ((error = arch_prepare_suspend())) if ((error = arch_prepare_suspend()))
return error; return error;
local_irq_disable(); local_irq_disable();
...@@ -580,15 +596,12 @@ int swsusp_suspend(void) ...@@ -580,15 +596,12 @@ int swsusp_suspend(void)
*/ */
if ((error = device_power_down(PMSG_FREEZE))) { if ((error = device_power_down(PMSG_FREEZE))) {
printk(KERN_ERR "Some devices failed to power down, aborting suspend\n"); printk(KERN_ERR "Some devices failed to power down, aborting suspend\n");
local_irq_enable(); goto Enable_irqs;
return error;
} }
if ((error = swsusp_swap_check())) { if ((error = save_highmem())) {
printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n"); printk(KERN_ERR "swsusp: Not enough free pages for highmem\n");
device_power_up(); goto Restore_highmem;
local_irq_enable();
return error;
} }
save_processor_state(); save_processor_state();
...@@ -596,8 +609,10 @@ int swsusp_suspend(void) ...@@ -596,8 +609,10 @@ int swsusp_suspend(void)
printk(KERN_ERR "Error %d suspending\n", error); printk(KERN_ERR "Error %d suspending\n", error);
/* Restore control flow magically appears here */ /* Restore control flow magically appears here */
restore_processor_state(); restore_processor_state();
Restore_highmem:
restore_highmem(); restore_highmem();
device_power_up(); device_power_up();
Enable_irqs:
local_irq_enable(); local_irq_enable();
return error; return error;
} }
...@@ -804,7 +819,7 @@ static int check_sig(void) ...@@ -804,7 +819,7 @@ static int check_sig(void)
* Reset swap signature now. * Reset swap signature now.
*/ */
error = bio_write_page(0, &swsusp_header); error = bio_write_page(0, &swsusp_header);
} else { } else {
return -EINVAL; return -EINVAL;
} }
if (!error) if (!error)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment