Hi!
quoted
quoted
quoted
If we specify a swap device for swsusp using resume= kernel argument and
that device doesn't exist in the swap list, we end up calling
swsusp_free() before we have allocated pagedir_save. That causes us to
explode when trying to free it.
Pavel, does that look right ?
It looks like a workaround. We should not call swsusp_free in case
device does not exists. Quick look did not reveal where the bug comes
from, can you try to trace it?
Pavel
Well, the bug comes from arch code calling swsusp_save() which fails,
then we call swsusp_free()
More specifically, arch suspend calls swsusp_save().
It fails and returns the error to the arch asm code, which itself
returns it to it's caller swsusp_suspend(), which does that:
if ((error = swsusp_arch_suspend()))
swsusp_free();
Ugh, swsusp_free should be totally unneccessary at this point; only
error returns are from the time before anything is allocated.
Does something like this help?
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -975,13 +975,6 @@ extern asmlinkage int swsusp_arch_resume
asmlinkage int swsusp_save(void)
{
- int error = 0;
-
- if ((error = swsusp_swap_check())) {
- printk(KERN_ERR "swsusp: FATAL: cannot find swap device, try "
- "swapon -a!\n");
- return error;
- }
return suspend_prepare_image();
}
@@ -999,12 +992,19 @@ int swsusp_suspend(void)
*/
if ((error = device_power_down(PMSG_FREEZE))) {
local_irq_enable();
- swsusp_free();
return error;
}
+
+ if ((error = swsusp_swap_check())) {
+ printk(KERN_ERR "swsusp: FATAL: cannot find swap device, try "
+ "swapon -a!\n");
+ local_irq_enable();
+ return error;
+ }
+
save_processor_state();
if ((error = swsusp_arch_suspend()))
- swsusp_free();
+ printk("Error %d suspending\n", error);
/* Restore control flow magically appears here */
restore_processor_state();
BUG_ON (nr_copy_pages_check != nr_copy_pages);