Commit d324cd65 authored by Patrick Mochel's avatar Patrick Mochel

[Power Mgmt] Merge first part of image writing code.

- Introduce helpers to swsusp - swsusp_write_page(), swsusp_data_write() and
  swsusp_data_free(). 
- Delete duplicate copies from pmdisk and fixup names in calls. 
- Clean up write_suspend_image() in swsusp and use the helpers.
parent 13c9f31a
......@@ -138,85 +138,9 @@ static int mark_swapfiles(swp_entry_t prev)
return error;
}
/**
* write_swap_page - Write one page to a fresh swap location.
* @addr: Address we're writing.
* @loc: Place to store the entry we used.
*
* Allocate a new swap entry and 'sync' it. Note we discard -EIO
* errors. That is an artifact left over from swsusp. It did not
* check the return of rw_swap_page_sync() at all, since most pages
* written back to swap would return -EIO.
* This is a partial improvement, since we will at least return other
* errors, though we need to eventually fix the damn code.
*/
static int write_swap_page(unsigned long addr, swp_entry_t * loc)
{
swp_entry_t entry;
int error = 0;
entry = get_swap_page();
if (swp_offset(entry) &&
swapfile_used[swp_type(entry)] == SWAPFILE_SUSPEND) {
error = rw_swap_page_sync(WRITE, entry,
virt_to_page(addr));
if (error == -EIO)
error = 0;
if (!error)
*loc = entry;
} else
error = -ENOSPC;
return error;
}
/**
* free_data - Free the swap entries used by the saved image.
*
* Walk the list of used swap entries and free each one.
*/
static void free_data(void)
{
swp_entry_t entry;
int i;
for (i = 0; i < nr_copy_pages; i++) {
entry = (pagedir_nosave + i)->swap_address;
if (entry.val)
swap_free(entry);
else
break;
(pagedir_nosave + i)->swap_address = (swp_entry_t){0};
}
}
/**
* write_data - Write saved image to swap.
*
* Walk the list of pages in the image and sync each one to swap.
*/
static int write_data(void)
{
int error = 0;
int i;
printk( "Writing data to swap (%d pages): ", nr_copy_pages );
for (i = 0; i < nr_copy_pages && !error; i++) {
if (!(i%100))
printk( "." );
error = write_swap_page((pagedir_nosave+i)->address,
&((pagedir_nosave+i)->swap_address));
}
printk(" %d Pages done.\n",i);
return error;
}
extern int swsusp_write_page(unsigned long addr, swp_entry_t * entry);
extern int swsusp_data_write(void);
extern void swsusp_data_free(void);
/**
* free_pagedir - Free pages used by the page directory.
......@@ -247,7 +171,7 @@ static int write_pagedir(void)
pmdisk_info.pagedir_pages = n;
printk( "Writing pagedir (%d pages)\n", n);
for (i = 0; i < n && !error; i++, addr += PAGE_SIZE)
error = write_swap_page(addr,&pmdisk_info.pagedir[i]);
error = swsusp_write_page(addr,&pmdisk_info.pagedir[i]);
return error;
}
......@@ -283,6 +207,7 @@ static void init_header(void)
pmdisk_info.cpus = num_online_cpus();
pmdisk_info.image_pages = nr_copy_pages;
dump_pmdisk_info();
}
/**
......@@ -297,8 +222,7 @@ static void init_header(void)
static int write_header(swp_entry_t * entry)
{
dump_pmdisk_info();
return write_swap_page((unsigned long)&pmdisk_info,entry);
return swsusp_write_page((unsigned long)&pmdisk_info,entry);
}
......@@ -313,9 +237,7 @@ static int write_suspend_image(void)
int error;
swp_entry_t prev = { 0 };
init_header();
if ((error = write_data()))
if ((error = swsusp_data_write()))
goto FreeData;
if ((error = write_pagedir()))
......@@ -330,7 +252,7 @@ static int write_suspend_image(void)
FreePagedir:
free_pagedir_entries();
FreeData:
free_data();
swsusp_data_free();
goto Done;
}
......
......@@ -295,6 +295,87 @@ void swsusp_swap_lock(void)
swap_list_unlock();
}
/**
* write_swap_page - Write one page to a fresh swap location.
* @addr: Address we're writing.
* @loc: Place to store the entry we used.
*
* Allocate a new swap entry and 'sync' it. Note we discard -EIO
* errors. That is an artifact left over from swsusp. It did not
* check the return of rw_swap_page_sync() at all, since most pages
* written back to swap would return -EIO.
* This is a partial improvement, since we will at least return other
* errors, though we need to eventually fix the damn code.
*/
int swsusp_write_page(unsigned long addr, swp_entry_t * loc)
{
swp_entry_t entry;
int error = 0;
entry = get_swap_page();
if (swp_offset(entry) &&
swapfile_used[swp_type(entry)] == SWAPFILE_SUSPEND) {
error = rw_swap_page_sync(WRITE, entry,
virt_to_page(addr));
if (error == -EIO)
error = 0;
if (!error)
*loc = entry;
} else
error = -ENOSPC;
return error;
}
/**
* free_data - Free the swap entries used by the saved image.
*
* Walk the list of used swap entries and free each one.
*/
void swsusp_data_free(void)
{
swp_entry_t entry;
int i;
for (i = 0; i < nr_copy_pages; i++) {
entry = (pagedir_nosave + i)->swap_address;
if (entry.val)
swap_free(entry);
else
break;
(pagedir_nosave + i)->swap_address = (swp_entry_t){0};
}
}
/**
* write_data - Write saved image to swap.
*
* Walk the list of pages in the image and sync each one to swap.
*/
int swsusp_data_write(void)
{
int error = 0;
int i;
printk( "Writing data to swap (%d pages): ", nr_copy_pages );
for (i = 0; i < nr_copy_pages && !error; i++) {
if (!(i%100))
printk( "." );
error = swsusp_write_page((pagedir_nosave+i)->address,
&((pagedir_nosave+i)->swap_address));
}
printk(" %d Pages done.\n",i);
return error;
}
/**
* write_suspend_image - Write entire image to disk.
*
......@@ -309,78 +390,39 @@ void swsusp_swap_lock(void)
static int write_suspend_image(void)
{
int i;
swp_entry_t entry, prev = { 0 };
int error = 0;
swp_entry_t entry = { 0 };
int nr_pgdir_pages = SUSPEND_PD_PAGES(nr_copy_pages);
union diskpage *cur, *buffer = (union diskpage *)get_zeroed_page(GFP_ATOMIC);
unsigned long address;
struct page *page;
unsigned long addr;
if (!buffer)
return -ENOMEM;
printk( "Writing data to swap (%d pages): ", nr_copy_pages );
for (i=0; i<nr_copy_pages; i++) {
if (!(i%100))
printk( "." );
entry = get_swap_page();
if (!entry.val)
panic("\nNot enough swapspace when writing data" );
if (swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND)
panic("\nPage %d: not enough swapspace on suspend device", i );
address = (pagedir_nosave+i)->address;
page = virt_to_page(address);
rw_swap_page_sync(WRITE, entry, page);
(pagedir_nosave+i)->swap_address = entry;
}
printk( "|\n" );
swsusp_data_write();
printk( "Writing pagedir (%d pages): ", nr_pgdir_pages);
for (i=0; i<nr_pgdir_pages; i++) {
cur = (union diskpage *)((char *) pagedir_nosave)+i;
BUG_ON ((char *) cur != (((char *) pagedir_nosave) + i*PAGE_SIZE));
addr = (unsigned long)pagedir_nosave;
for (i=0; i<nr_pgdir_pages && !error; i++, addr += PAGE_SIZE) {
cur = (union diskpage *)addr;
cur->link.next = entry;
printk( "." );
entry = get_swap_page();
if (!entry.val) {
printk(KERN_CRIT "Not enough swapspace when writing pgdir\n" );
panic("Don't know how to recover");
free_page((unsigned long) buffer);
return -ENOSPC;
}
if(swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND)
panic("\nNot enough swapspace for pagedir on suspend device" );
BUG_ON (sizeof(swp_entry_t) != sizeof(long));
BUG_ON (PAGE_SIZE % sizeof(struct pbe));
cur->link.next = prev;
page = virt_to_page((unsigned long)cur);
rw_swap_page_sync(WRITE, entry, page);
prev = entry;
error = swsusp_write_page(addr,&entry);
}
printk("H");
BUG_ON (sizeof(struct suspend_header) > PAGE_SIZE-sizeof(swp_entry_t));
BUG_ON (sizeof(union diskpage) != PAGE_SIZE);
BUG_ON (sizeof(struct link) != PAGE_SIZE);
entry = get_swap_page();
if (!entry.val)
panic( "\nNot enough swapspace when writing header" );
if (swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND)
panic("\nNot enough swapspace for header on suspend device" );
cur = (void *) buffer;
if (fill_suspend_header(&cur->sh))
BUG(); /* Not a BUG_ON(): we want fill_suspend_header to be called, always */
cur->link.next = prev;
page = virt_to_page((unsigned long)cur);
rw_swap_page_sync(WRITE, entry, page);
prev = entry;
cur->link.next = entry;
if ((error = swsusp_write_page((unsigned long)cur,&entry)))
return error;
printk( "S" );
mark_swapfiles(prev, MARK_SWAP_SUSPEND);
mark_swapfiles(entry, MARK_SWAP_SUSPEND);
printk( "|\n" );
MDELAY(1000);
......
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