Commit b6fb7271 authored by Patrick Mochel's avatar Patrick Mochel

[Power Mgmt] Merge pmdisk and swsusp signature handling.

- Move struct pmdisk_header definition to swsusp and change name to struct
  swsusp_header.
- Statically allocate one (swsusp_header), and use it during mark_swapfiles()
  and when checking sig on resume.
- Move check_sig() from pmdisk to swsusp.
- Wrap with swsusp_verify(), and move check_header() there. 
- Fix up calls in pmdisk and swsusp.
- Make new wrapper swsusp_close_swap() and call from write_suspend_image().
- Look for swsusp_info info in swsusp_header.swsusp_info, instead of magic
  location at end of struct. 
parent 4196815a
...@@ -63,15 +63,6 @@ extern int pagedir_order; ...@@ -63,15 +63,6 @@ extern int pagedir_order;
extern struct swsusp_info swsusp_info; extern struct swsusp_info swsusp_info;
#define PMDISK_SIG "pmdisk-swap1"
struct pmdisk_header {
char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
swp_entry_t pmdisk_info;
char orig_sig[10];
char sig[10];
} __attribute__((packed, aligned(PAGE_SIZE))) pmdisk_header;
/* /*
* XXX: We try to keep some more pages free so that I/O operations succeed * XXX: We try to keep some more pages free so that I/O operations succeed
* without paging. Might this be more? * without paging. Might this be more?
...@@ -89,35 +80,10 @@ struct pmdisk_header { ...@@ -89,35 +80,10 @@ struct pmdisk_header {
#define SWAPFILE_SUSPEND 1 /* This is the suspending device */ #define SWAPFILE_SUSPEND 1 /* This is the suspending device */
#define SWAPFILE_IGNORED 2 /* Those are other swap devices ignored for suspension */ #define SWAPFILE_IGNORED 2 /* Those are other swap devices ignored for suspension */
extern unsigned short swapfile_used[MAX_SWAPFILES];
extern unsigned short root_swap;
extern int swsusp_swap_check(void); extern int swsusp_swap_check(void);
extern void swsusp_swap_lock(void); extern void swsusp_swap_lock(void);
static int mark_swapfiles(swp_entry_t prev)
{
int error;
rw_swap_page_sync(READ,
swp_entry(root_swap, 0),
virt_to_page((unsigned long)&pmdisk_header));
if (!memcmp("SWAP-SPACE",pmdisk_header.sig,10) ||
!memcmp("SWAPSPACE2",pmdisk_header.sig,10)) {
memcpy(pmdisk_header.orig_sig,pmdisk_header.sig,10);
memcpy(pmdisk_header.sig,PMDISK_SIG,10);
pmdisk_header.pmdisk_info = prev;
error = rw_swap_page_sync(WRITE,
swp_entry(root_swap, 0),
virt_to_page((unsigned long)
&pmdisk_header));
} else {
pr_debug("pmdisk: Partition is not swap space.\n");
error = -ENODEV;
}
return error;
}
extern int swsusp_write_page(unsigned long addr, swp_entry_t * entry); extern int swsusp_write_page(unsigned long addr, swp_entry_t * entry);
extern int swsusp_data_write(void); extern int swsusp_data_write(void);
extern void swsusp_data_free(void); extern void swsusp_data_free(void);
...@@ -156,7 +122,7 @@ static int write_pagedir(void) ...@@ -156,7 +122,7 @@ static int write_pagedir(void)
} }
extern void swsusp_init_header(void); extern void swsusp_init_header(void);
extern int swsusp_write_header(swp_entry_t*); extern int swsusp_close_swap(void);
/** /**
* write_suspend_image - Write entire image and metadata. * write_suspend_image - Write entire image and metadata.
...@@ -166,7 +132,6 @@ extern int swsusp_write_header(swp_entry_t*); ...@@ -166,7 +132,6 @@ extern int swsusp_write_header(swp_entry_t*);
static int write_suspend_image(void) static int write_suspend_image(void)
{ {
int error; int error;
swp_entry_t prev = { 0 };
swsusp_init_header(); swsusp_init_header();
if ((error = swsusp_data_write())) if ((error = swsusp_data_write()))
...@@ -175,10 +140,8 @@ static int write_suspend_image(void) ...@@ -175,10 +140,8 @@ static int write_suspend_image(void)
if ((error = write_pagedir())) if ((error = write_pagedir()))
goto FreePagedir; goto FreePagedir;
if ((error = swsusp_write_header(&prev))) if ((error = swsusp_close_swap()))
goto FreePagedir; goto FreePagedir;
error = mark_swapfiles(prev);
Done: Done:
return error; return error;
FreePagedir: FreePagedir:
...@@ -227,30 +190,6 @@ extern int bio_write_page(pgoff_t page_off, void * page); ...@@ -227,30 +190,6 @@ extern int bio_write_page(pgoff_t page_off, void * page);
extern dev_t __init name_to_dev_t(const char *line); extern dev_t __init name_to_dev_t(const char *line);
static int __init check_sig(void)
{
int error;
memset(&pmdisk_header,0,sizeof(pmdisk_header));
if ((error = bio_read_page(0,&pmdisk_header)))
return error;
if (!memcmp(PMDISK_SIG,pmdisk_header.sig,10)) {
memcpy(pmdisk_header.sig,pmdisk_header.orig_sig,10);
/*
* Reset swap signature now.
*/
error = bio_write_page(0,&pmdisk_header);
} else {
pr_debug(KERN_ERR "pmdisk: Invalid partition type.\n");
return -EINVAL;
}
if (!error)
pr_debug("pmdisk: Signature found, resuming\n");
return error;
}
static int __init read_pagedir(void) static int __init read_pagedir(void)
{ {
unsigned long addr; unsigned long addr;
...@@ -282,13 +221,11 @@ static int __init read_pagedir(void) ...@@ -282,13 +221,11 @@ static int __init read_pagedir(void)
static int __init read_suspend_image(void) static int __init read_suspend_image(void)
{ {
extern int swsusp_data_read(void); extern int swsusp_data_read(void);
extern int swsusp_check_header(swp_entry_t); extern int swsusp_verify(void);
int error = 0; int error = 0;
if ((error = check_sig())) if ((error = swsusp_verify()))
return error;
if ((error = swsusp_check_header(pmdisk_header.pmdisk_info)))
return error; return error;
if ((error = read_pagedir())) if ((error = read_pagedir()))
return error; return error;
......
...@@ -111,6 +111,15 @@ suspend_pagedir_t *pagedir_nosave __nosavedata = NULL; ...@@ -111,6 +111,15 @@ suspend_pagedir_t *pagedir_nosave __nosavedata = NULL;
suspend_pagedir_t *pagedir_save; suspend_pagedir_t *pagedir_save;
int pagedir_order __nosavedata = 0; int pagedir_order __nosavedata = 0;
#define SWSUSP_SIG "S1SUSPEND"
struct swsusp_header {
char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
swp_entry_t swsusp_info;
char orig_sig[10];
char sig[10];
} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header;
struct swsusp_info swsusp_info; struct swsusp_info swsusp_info;
struct link { struct link {
...@@ -161,49 +170,32 @@ static const char name_resume[] = "Resume Machine: "; ...@@ -161,49 +170,32 @@ static const char name_resume[] = "Resume Machine: ";
#define SWAPFILE_SUSPEND 1 /* This is the suspending device */ #define SWAPFILE_SUSPEND 1 /* This is the suspending device */
#define SWAPFILE_IGNORED 2 /* Those are other swap devices ignored for suspension */ #define SWAPFILE_IGNORED 2 /* Those are other swap devices ignored for suspension */
unsigned short swapfile_used[MAX_SWAPFILES]; static unsigned short swapfile_used[MAX_SWAPFILES];
unsigned short root_swap; static unsigned short root_swap;
#define MARK_SWAP_SUSPEND 0
#define MARK_SWAP_RESUME 2
static void mark_swapfiles(swp_entry_t prev, int mode) static int mark_swapfiles(swp_entry_t prev)
{ {
swp_entry_t entry; int error;
union diskpage *cur;
struct page *page;
if (root_swap == 0xFFFF) /* ignored */ rw_swap_page_sync(READ,
return; swp_entry(root_swap, 0),
virt_to_page((unsigned long)&swsusp_header));
page = alloc_page(GFP_ATOMIC); if (!memcmp("SWAP-SPACE",swsusp_header.sig,10) ||
if (!page) !memcmp("SWAPSPACE2",swsusp_header.sig,10)) {
panic("Out of memory in mark_swapfiles"); memcpy(swsusp_header.orig_sig,swsusp_header.sig,10);
cur = page_address(page); memcpy(swsusp_header.sig,SWSUSP_SIG,10);
/* XXX: this is dirty hack to get first page of swap file */ swsusp_header.swsusp_info = prev;
entry = swp_entry(root_swap, 0); error = rw_swap_page_sync(WRITE,
rw_swap_page_sync(READ, entry, page); swp_entry(root_swap, 0),
virt_to_page((unsigned long)
if (mode == MARK_SWAP_RESUME) { &swsusp_header));
if (!memcmp("S1",cur->swh.magic.magic,2))
memcpy(cur->swh.magic.magic,"SWAP-SPACE",10);
else if (!memcmp("S2",cur->swh.magic.magic,2))
memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
else printk("%sUnable to find suspended-data signature (%.10s - misspelled?\n",
name_resume, cur->swh.magic.magic);
} else { } else {
if ((!memcmp("SWAP-SPACE",cur->swh.magic.magic,10))) pr_debug("swsusp: Partition is not swap space.\n");
memcpy(cur->swh.magic.magic,"S1SUSP....",10); error = -ENODEV;
else if ((!memcmp("SWAPSPACE2",cur->swh.magic.magic,10)))
memcpy(cur->swh.magic.magic,"S2SUSP....",10);
else panic("\nSwapspace is not swapspace (%.10s)\n", cur->swh.magic.magic);
cur->link.next = prev; /* prev is the first/last swap page of the resume area */
/* link.next lies *no more* in last 4/8 bytes of magic */
} }
rw_swap_page_sync(WRITE, entry, page); return error;
__free_page(page);
} }
/* /*
* Check whether the swap device is the specified resume * Check whether the swap device is the specified resume
* device, irrespective of whether they are specified by * device, irrespective of whether they are specified by
...@@ -400,11 +392,25 @@ void swsusp_init_header(void) ...@@ -400,11 +392,25 @@ void swsusp_init_header(void)
* entrance. On exit, it contains the location of the header. * entrance. On exit, it contains the location of the header.
*/ */
int swsusp_write_header(swp_entry_t * entry) static int write_header(swp_entry_t * entry)
{ {
return swsusp_write_page((unsigned long)&swsusp_info,entry); return swsusp_write_page((unsigned long)&swsusp_info,entry);
} }
int swsusp_close_swap(void)
{
swp_entry_t entry;
int error;
error = write_header(&entry);
printk( "S" );
if (!error)
error = mark_swapfiles(entry);
printk( "|\n" );
return error;
}
/** /**
* write_suspend_image - Write entire image to disk. * write_suspend_image - Write entire image to disk.
* *
...@@ -429,6 +435,7 @@ static int write_suspend_image(void) ...@@ -429,6 +435,7 @@ static int write_suspend_image(void)
return -ENOMEM; return -ENOMEM;
swsusp_data_write(); swsusp_data_write();
swsusp_init_header();
printk( "Writing pagedir (%d pages): ", nr_pgdir_pages); printk( "Writing pagedir (%d pages): ", nr_pgdir_pages);
addr = (unsigned long)pagedir_nosave; addr = (unsigned long)pagedir_nosave;
...@@ -442,12 +449,8 @@ static int write_suspend_image(void) ...@@ -442,12 +449,8 @@ static int write_suspend_image(void)
BUG_ON (sizeof(union diskpage) != PAGE_SIZE); BUG_ON (sizeof(union diskpage) != PAGE_SIZE);
BUG_ON (sizeof(struct link) != PAGE_SIZE); BUG_ON (sizeof(struct link) != PAGE_SIZE);
swsusp_init_header();
swsusp_info.pagedir[0] = entry; swsusp_info.pagedir[0] = entry;
error = swsusp_write_header(&entry); swsusp_close_swap();
printk( "S" );
mark_swapfiles(entry, MARK_SWAP_SUSPEND);
printk( "|\n" );
MDELAY(1000); MDELAY(1000);
return 0; return 0;
...@@ -906,9 +909,6 @@ static void suspend_finish(void) ...@@ -906,9 +909,6 @@ static void suspend_finish(void)
restore_highmem(); restore_highmem();
#endif #endif
device_resume(); device_resume();
PRINTK( "Fixing swap signatures... " );
mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
PRINTK( "ok\n" );
#ifdef SUSPEND_CONSOLE #ifdef SUSPEND_CONSOLE
acquire_console_sem(); acquire_console_sem();
...@@ -1217,12 +1217,12 @@ static const char * __init sanity_check(void) ...@@ -1217,12 +1217,12 @@ static const char * __init sanity_check(void)
} }
int __init swsusp_check_header(swp_entry_t loc) static int __init check_header(void)
{ {
const char * reason = NULL; const char * reason = NULL;
int error; int error;
if ((error = bio_read_page(swp_offset(loc), &swsusp_info))) if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info)))
return error; return error;
/* Is this same machine? */ /* Is this same machine? */
...@@ -1234,6 +1234,38 @@ int __init swsusp_check_header(swp_entry_t loc) ...@@ -1234,6 +1234,38 @@ int __init swsusp_check_header(swp_entry_t loc)
return error; return error;
} }
static int __init check_sig(void)
{
int error;
memset(&swsusp_header,0,sizeof(swsusp_header));
if ((error = bio_read_page(0,&swsusp_header)))
return error;
if (!memcmp(SWSUSP_SIG,swsusp_header.sig,10)) {
memcpy(swsusp_header.sig,swsusp_header.orig_sig,10);
/*
* Reset swap signature now.
*/
error = bio_write_page(0,&swsusp_header);
} else {
pr_debug(KERN_ERR "swsusp: Invalid partition type.\n");
return -EINVAL;
}
if (!error)
pr_debug("swsusp: Signature found, resuming\n");
return error;
}
int __init swsusp_verify(void)
{
int error;
if (!(error = check_sig()))
error = check_header();
return error;
}
/** /**
...@@ -1273,6 +1305,9 @@ static int __init __read_suspend_image(int noresume) ...@@ -1273,6 +1305,9 @@ static int __init __read_suspend_image(int noresume)
int i, nr_pgdir_pages; int i, nr_pgdir_pages;
int error; int error;
if ((error = swsusp_verify()))
return error;
cur = (union diskpage *)get_zeroed_page(GFP_ATOMIC); cur = (union diskpage *)get_zeroed_page(GFP_ATOMIC);
if (!cur) if (!cur)
return -ENOMEM; return -ENOMEM;
...@@ -1282,40 +1317,8 @@ static int __init __read_suspend_image(int noresume) ...@@ -1282,40 +1317,8 @@ static int __init __read_suspend_image(int noresume)
next.val = swp_offset(next); \ next.val = swp_offset(next); \
} }
if (bio_read_page(0, cur)) return -EIO;
if ((!memcmp("SWAP-SPACE",cur->swh.magic.magic,10)) ||
(!memcmp("SWAPSPACE2",cur->swh.magic.magic,10))) {
printk(KERN_ERR "%sThis is normal swap space\n", name_resume );
return -EINVAL;
}
PREPARENEXT; /* We have to read next position before we overwrite it */
if (!memcmp("S1",cur->swh.magic.magic,2))
memcpy(cur->swh.magic.magic,"SWAP-SPACE",10);
else if (!memcmp("S2",cur->swh.magic.magic,2))
memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
else {
if (noresume) if (noresume)
return -EINVAL; return 0;
panic("%sUnable to find suspended-data signature (%.10s - misspelled?\n",
name_resume, cur->swh.magic.magic);
}
if (noresume) {
/* We don't do a sanity check here: we want to restore the swap
whatever version of kernel made the suspend image;
We need to write swap, but swap is *not* enabled so
we must write the device directly */
printk("%s: Fixing swap signatures %s...\n", name_resume, resume_file);
bio_write_page(0, cur);
}
printk( "%sSignature found, resuming\n", name_resume );
MDELAY(1000);
if ((error = swsusp_check_header(next)))
return error;
next = swsusp_info.pagedir[0]; next = swsusp_info.pagedir[0];
next.val = swp_offset(next); next.val = swp_offset(next);
......
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