static int __init read_suspend_image(void) { int error = 0; if ((error = check_sig())) return error; if ((error = check_header())) return error; if ((error = read_pagedir())) return error; if ((error = relocate_pagedir())) goto FreePagedir; if ((error = check_pagedir())) goto FreePagedir; if ((error = read_image_data())) goto FreePagedir; Done: return error; FreePagedir: free_pages((unsigned long)pm_pagedir_nosave,pagedir_order); goto Done; }
static int __read_suspend_image(struct block_device *bdev, union diskpage *cur, int noresume) { swp_entry_t next; int i, nr_pgdir_pages; #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; } 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) return -EINVAL; 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); bdev_write_page(bdev, 0, cur); } 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; PREPARENEXT; pagedir_save = cur->sh.suspend_pagedir; nr_copy_pages = cur->sh.num_pbes; nr_pgdir_pages = SUSPEND_PD_PAGES(nr_copy_pages); 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; PRINTK( "%sReading pagedir, ", name_resume ); /* We get pages in reverse order of saving! */ 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; PREPARENEXT; } BUG_ON (next.val); if (relocate_pagedir()) return -ENOMEM; if (check_pagedir()) return -ENOMEM; printk( "Reading image data (%d pages): ", nr_copy_pages ); for(i=0; i < nr_copy_pages; i++) { swp_entry_t swap_address = (pagedir_nosave+i)->swap_address; if (!(i%100)) 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; } printk( "|\n" ); return 0; }