summaryrefslogtreecommitdiff
path: root/kernel/power
diff options
context:
space:
mode:
authorPatrick Mochel <mochel@osdl.org>2003-08-29 02:36:54 -0700
committerPatrick Mochel <mochel@osdl.org>2003-08-29 02:36:54 -0700
commit7431d7eb143a53440d29c6dbfeda69b2045896be (patch)
tree2c9e4ec370865ab5de108760f60e131149f04901 /kernel/power
parent89f518c1a12fcd9e3347cc4532e8a79f1f04a70c (diff)
[swsusp] Minor cleanups in read_suspend_image()
- Make resume_bdev global to file, so we don't have to pass it around (we always use the same one, so it shouldn't make a difference). - Allocate cur in read_suspend_image(), since it's the only function that uses it. - Check all errors and make sure we free cur if any happen. - Make sure to return errors from the functions called, not our own. - Free the pagedir if we hit an error after we allocate it.
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/swsusp.c96
1 files changed, 54 insertions, 42 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 7ae04d8eefac..62690f4a1c48 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -673,12 +673,13 @@ static int __init sanity_check(struct suspend_header *sh)
return 0;
}
-static int __init bdev_read_page(struct block_device *bdev,
- long pos, void *buf)
+static struct block_device * resume_bdev;
+
+static int __init bdev_read_page(long pos, void *buf)
{
struct buffer_head *bh;
BUG_ON (pos%PAGE_SIZE);
- bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
+ bh = __bread(resume_bdev, pos/PAGE_SIZE, PAGE_SIZE);
if (!bh || (!bh->b_data)) {
return -1;
}
@@ -690,24 +691,24 @@ static int __init bdev_read_page(struct block_device *bdev,
extern dev_t __init name_to_dev_t(const char *line);
-static int __init read_suspend_image(struct block_device *bdev,
- union diskpage *cur)
+static int __init read_suspend_image(void)
{
swp_entry_t next;
int i, nr_pgdir_pages;
+ union diskpage *cur;
+ int error = 0;
+
+ cur = (union diskpage *)get_zeroed_page(GFP_ATOMIC);
+ if (!cur)
+ return -ENOMEM;
#define PREPARENEXT \
{ next = cur->link.next; \
next.val = swp_offset(next) * PAGE_SIZE; \
}
- if (bdev_read_page(bdev, 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;
- }
+ if ((error = bdev_read_page(0, cur)))
+ goto Done;
PREPARENEXT; /* We have to read next position before we overwrite it */
@@ -715,18 +716,25 @@ static int __init read_suspend_image(struct block_device *bdev,
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("swsusp: %s: Unable to find suspended-data signature (%.10s - misspelled?\n",
- name_resume, cur->swh.magic.magic);
- return -EFAULT;
+ else if ((!memcmp("SWAP-SPACE",cur->swh.magic.magic,10)) ||
+ (!memcmp("SWAPSPACE2",cur->swh.magic.magic,10))) {
+ printk(KERN_ERR "swsusp: Partition is normal swap space\n");
+ error = -EINVAL;
+ goto Done;
+ } else {
+ printk(KERN_ERR "swsusp: Invalid partition type.\n");
+ error = -EINVAL;
+ goto Done;
}
printk( "%sSignature found, resuming\n", name_resume );
MDELAY(1000);
- if (bdev_read_page(bdev, next.val, cur)) return -EIO;
- if (sanity_check(&cur->sh)) /* Is this same machine? */
- return -EPERM;
+ if ((error = bdev_read_page(next.val, cur)))
+ goto Done;
+ /* Is this same machine? */
+ if ((error = sanity_check(&cur->sh)))
+ goto Done;
PREPARENEXT;
pagedir_save = cur->sh.suspend_pagedir;
@@ -735,8 +743,10 @@ static int __init read_suspend_image(struct block_device *bdev,
pagedir_order = get_bitmask_order(nr_pgdir_pages);
pagedir_nosave = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC, pagedir_order);
- if (!pagedir_nosave)
- return -ENOMEM;
+ if (!pagedir_nosave) {
+ error = -ENOMEM;
+ goto Done;
+ }
PRINTK( "%sReading pagedir, ", name_resume );
@@ -744,15 +754,17 @@ static int __init read_suspend_image(struct block_device *bdev,
for (i=nr_pgdir_pages-1; i>=0; i--) {
BUG_ON (!next.val);
cur = (union diskpage *)((char *) pagedir_nosave)+i;
- if (bdev_read_page(bdev, next.val, cur)) return -EIO;
+ error = bdev_read_page(next.val, cur);
+ if (error)
+ goto FreePagedir;
PREPARENEXT;
}
BUG_ON (next.val);
- if (relocate_pagedir())
- return -ENOMEM;
- if (check_pagedir())
- return -ENOMEM;
+ if ((error = relocate_pagedir()))
+ goto FreePagedir;
+ if ((error = check_pagedir()))
+ goto FreePagedir;
printk( "Reading image data (%d pages): ", nr_copy_pages );
for(i=0; i < nr_copy_pages; i++) {
@@ -761,11 +773,18 @@ static int __init read_suspend_image(struct block_device *bdev,
printk( "." );
/* You do not need to check for overlaps...
... check_pagedir already did this work */
- if (bdev_read_page(bdev, swp_offset(swap_address) * PAGE_SIZE, (char *)((pagedir_nosave+i)->address)))
- return -EIO;
+ error = bdev_read_page(swp_offset(swap_address) * PAGE_SIZE,
+ (char *)((pagedir_nosave+i)->address));
+ if (error)
+ goto FreePagedir;
}
printk( "|\n" );
- return 0;
+ Done:
+ free_page((unsigned long)cur);
+ return error;
+ FreePagedir:
+ free_pages((unsigned long)pagedir_nosave,pagedir_order);
+ goto Done;
}
/**
@@ -804,7 +823,6 @@ int swsusp_write(void)
int __init swsusp_read(void)
{
- union diskpage *cur;
int error;
char b[BDEVNAME_SIZE];
@@ -815,19 +833,13 @@ int __init swsusp_read(void)
printk("swsusp: Resume From Partition: %s, Device: %s\n",
resume_file, __bdevname(resume_device, b));
- cur = (union diskpage *)get_zeroed_page(GFP_ATOMIC);
- if (cur) {
- struct block_device *bdev;
- bdev = open_by_devnum(resume_device, FMODE_READ, BDEV_RAW);
- if (!IS_ERR(bdev)) {
- set_blocksize(bdev, PAGE_SIZE);
- error = read_suspend_image(bdev, cur);
- blkdev_put(bdev, BDEV_RAW);
- } else
- error = PTR_ERR(bdev);
- free_page((unsigned long)cur);
+ resume_bdev = open_by_devnum(resume_device, FMODE_READ, BDEV_RAW);
+ if (!IS_ERR(resume_bdev)) {
+ set_blocksize(resume_bdev, PAGE_SIZE);
+ error = read_suspend_image();
+ blkdev_put(resume_bdev, BDEV_RAW);
} else
- error = -ENOMEM;
+ error = PTR_ERR(resume_bdev);
if (!error)
PRINTK("Reading resume file was successful\n");