|
@@ -104,13 +104,7 @@ static struct swsusp_info swsusp_info;
|
|
|
* Saving part...
|
|
|
*/
|
|
|
|
|
|
-/* We memorize in swapfile_used what swap devices are used for suspension */
|
|
|
-#define SWAPFILE_UNUSED 0
|
|
|
-#define SWAPFILE_SUSPEND 1 /* This is the suspending device */
|
|
|
-#define SWAPFILE_IGNORED 2 /* Those are other swap devices ignored for suspension */
|
|
|
-
|
|
|
-static unsigned short swapfile_used[MAX_SWAPFILES];
|
|
|
-static unsigned short root_swap;
|
|
|
+static unsigned short root_swap = 0xffff;
|
|
|
|
|
|
static int mark_swapfiles(swp_entry_t prev)
|
|
|
{
|
|
@@ -146,7 +140,7 @@ static int mark_swapfiles(swp_entry_t prev)
|
|
|
* devfs, since the resume code can only recognize the form /dev/hda4,
|
|
|
* but the suspend code would see the long name.)
|
|
|
*/
|
|
|
-static int is_resume_device(const struct swap_info_struct *swap_info)
|
|
|
+static inline int is_resume_device(const struct swap_info_struct *swap_info)
|
|
|
{
|
|
|
struct file *file = swap_info->swap_file;
|
|
|
struct inode *inode = file->f_dentry->d_inode;
|
|
@@ -156,55 +150,23 @@ static int is_resume_device(const struct swap_info_struct *swap_info)
|
|
|
}
|
|
|
|
|
|
static int swsusp_swap_check(void) /* This is called before saving image */
|
|
|
-{
|
|
|
- int i, len;
|
|
|
-
|
|
|
- len=strlen(resume_file);
|
|
|
- root_swap = 0xFFFF;
|
|
|
-
|
|
|
- spin_lock(&swap_lock);
|
|
|
- for (i=0; i<MAX_SWAPFILES; i++) {
|
|
|
- if (!(swap_info[i].flags & SWP_WRITEOK)) {
|
|
|
- swapfile_used[i]=SWAPFILE_UNUSED;
|
|
|
- } else {
|
|
|
- if (!len) {
|
|
|
- printk(KERN_WARNING "resume= option should be used to set suspend device" );
|
|
|
- if (root_swap == 0xFFFF) {
|
|
|
- swapfile_used[i] = SWAPFILE_SUSPEND;
|
|
|
- root_swap = i;
|
|
|
- } else
|
|
|
- swapfile_used[i] = SWAPFILE_IGNORED;
|
|
|
- } else {
|
|
|
- /* we ignore all swap devices that are not the resume_file */
|
|
|
- if (is_resume_device(&swap_info[i])) {
|
|
|
- swapfile_used[i] = SWAPFILE_SUSPEND;
|
|
|
- root_swap = i;
|
|
|
- } else {
|
|
|
- swapfile_used[i] = SWAPFILE_IGNORED;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- spin_unlock(&swap_lock);
|
|
|
- return (root_swap != 0xffff) ? 0 : -ENODEV;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * This is called after saving image so modification
|
|
|
- * will be lost after resume... and that's what we want.
|
|
|
- * we make the device unusable. A new call to
|
|
|
- * lock_swapdevices can unlock the devices.
|
|
|
- */
|
|
|
-static void lock_swapdevices(void)
|
|
|
{
|
|
|
int i;
|
|
|
|
|
|
+ if (!swsusp_resume_device)
|
|
|
+ return -ENODEV;
|
|
|
spin_lock(&swap_lock);
|
|
|
- for (i = 0; i< MAX_SWAPFILES; i++)
|
|
|
- if (swapfile_used[i] == SWAPFILE_IGNORED) {
|
|
|
- swap_info[i].flags ^= SWP_WRITEOK;
|
|
|
+ for (i = 0; i < MAX_SWAPFILES; i++) {
|
|
|
+ if (!(swap_info[i].flags & SWP_WRITEOK))
|
|
|
+ continue;
|
|
|
+ if (is_resume_device(swap_info + i)) {
|
|
|
+ spin_unlock(&swap_lock);
|
|
|
+ root_swap = i;
|
|
|
+ return 0;
|
|
|
}
|
|
|
+ }
|
|
|
spin_unlock(&swap_lock);
|
|
|
+ return -ENODEV;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -222,19 +184,14 @@ static void lock_swapdevices(void)
|
|
|
static int write_page(unsigned long addr, swp_entry_t *loc)
|
|
|
{
|
|
|
swp_entry_t entry;
|
|
|
- int error = 0;
|
|
|
+ int error = -ENOSPC;
|
|
|
|
|
|
- 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)
|
|
|
+ entry = get_swap_page_of_type(root_swap);
|
|
|
+ if (swp_offset(entry)) {
|
|
|
+ error = rw_swap_page_sync(WRITE, entry, virt_to_page(addr));
|
|
|
+ if (!error || error == -EIO)
|
|
|
*loc = entry;
|
|
|
- } else
|
|
|
- error = -ENOSPC;
|
|
|
+ }
|
|
|
return error;
|
|
|
}
|
|
|
|
|
@@ -539,31 +496,38 @@ static int save_image_metadata(struct pbe *pblist,
|
|
|
* 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.
|
|
|
+ * space avaiable from the resume partition.
|
|
|
*/
|
|
|
|
|
|
static int enough_swap(unsigned int nr_pages)
|
|
|
{
|
|
|
- struct sysinfo i;
|
|
|
+ unsigned int free_swap = swap_info[root_swap].pages -
|
|
|
+ swap_info[root_swap].inuse_pages;
|
|
|
|
|
|
- si_swapinfo(&i);
|
|
|
- pr_debug("swsusp: available swap: %lu pages\n", i.freeswap);
|
|
|
- return i.freeswap > (nr_pages + PAGES_FOR_IO +
|
|
|
+ pr_debug("swsusp: free swap pages: %u\n", free_swap);
|
|
|
+ return free_swap > (nr_pages + PAGES_FOR_IO +
|
|
|
(nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * write_suspend_image - Write entire image and metadata.
|
|
|
+ * swsusp_write - Write entire image and metadata.
|
|
|
+ *
|
|
|
+ * 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
|
|
|
+ * filesystem clean: it is not. (And it does not matter, if we resume
|
|
|
+ * correctly, we'll mark system clean, anyway.)
|
|
|
*/
|
|
|
-static int write_suspend_image(struct pbe *pblist, unsigned int nr_pages)
|
|
|
+
|
|
|
+int swsusp_write(struct pbe *pblist, unsigned int nr_pages)
|
|
|
{
|
|
|
struct swap_map_page *swap_map;
|
|
|
struct swap_map_handle handle;
|
|
|
int error;
|
|
|
|
|
|
+ if ((error = swsusp_swap_check())) {
|
|
|
+ printk(KERN_ERR "swsusp: Cannot find swap device, try swapon -a.\n");
|
|
|
+ return error;
|
|
|
+ }
|
|
|
if (!enough_swap(nr_pages)) {
|
|
|
printk(KERN_ERR "swsusp: Not enough free swap\n");
|
|
|
return -ENOSPC;
|
|
@@ -601,26 +565,6 @@ Free_image_entries:
|
|
|
goto Free_swap_map;
|
|
|
}
|
|
|
|
|
|
-/* 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
|
|
|
- * filesystem clean: it is not. (And it does not matter, if we resume
|
|
|
- * correctly, we'll mark system clean, anyway.)
|
|
|
- */
|
|
|
-int swsusp_write(struct pbe *pblist, unsigned int nr_pages)
|
|
|
-{
|
|
|
- int error;
|
|
|
-
|
|
|
- if ((error = swsusp_swap_check())) {
|
|
|
- printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n");
|
|
|
- return error;
|
|
|
- }
|
|
|
- lock_swapdevices();
|
|
|
- error = write_suspend_image(pblist, nr_pages);
|
|
|
- /* This will unlock ignored swap devices since writing is finished */
|
|
|
- lock_swapdevices();
|
|
|
- return error;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* swsusp_shrink_memory - Try to free as much memory as needed
|
|
|
*
|