static int write_page(void *buf, unsigned long offset) { swp_entry_t entry; int error = -ENOSPC; if (offset) { entry = swp_entry(root_swap, offset); error = rw_swap_page_sync(WRITE, entry, virt_to_page(buf)); } return error; }
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; }
static int mark_swapfiles(swp_entry_t start) { int error; rw_swap_page_sync(READ, swp_entry(root_swap, 0), virt_to_page((unsigned long)&swsusp_header)); if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) || !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); memcpy(swsusp_header.sig,SWSUSP_SIG, 10); swsusp_header.image = start; error = rw_swap_page_sync(WRITE, swp_entry(root_swap, 0), virt_to_page((unsigned long) &swsusp_header)); } else { pr_debug("swsusp: Partition is not swap space.\n"); error = -ENODEV; } return error; }
static void mark_swapfiles(swp_entry_t prev, int mode) { swp_entry_t entry; union diskpage *cur; struct page *page; if (root_swap == 0xFFFF) /* ignored */ return; page = alloc_page(GFP_ATOMIC); if (!page) panic("Out of memory in mark_swapfiles"); cur = page_address(page); /* XXX: this is dirty hack to get first page of swap file */ entry = swp_entry(root_swap, 0); rw_swap_page_sync(READ, entry, page); if (mode == MARK_SWAP_RESUME) { 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 { if ((!memcmp("SWAP-SPACE",cur->swh.magic.magic,10))) memcpy(cur->swh.magic.magic,"S1SUSP....",10); 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); __free_page(page); }
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; }
/** * write_suspend_image - Write entire image to disk. * * After writing suspend signature to the disk, suspend may no * longer fail: we have ready-to-run image in swap, and rollback * would happen on next reboot -- corrupting data. * * Note: The buffer we allocate to use to write the suspend header is * not freed; its not needed since system is going down anyway * (plus it causes oops and I'm lazy^H^H^H^Htoo busy). */ static int write_suspend_image(void) { int i; swp_entry_t entry, prev = { 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; 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( "." ); if (!(entry = get_swap_page()).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" ); 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)); printk( "." ); if (!(entry = get_swap_page()).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; } printk("H"); BUG_ON (sizeof(struct suspend_header) > PAGE_SIZE-sizeof(swp_entry_t)); BUG_ON (sizeof(union diskpage) != PAGE_SIZE); if (!(entry = get_swap_page()).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)) panic("\nOut of memory while writing header"); cur->link.next = prev; page = virt_to_page((unsigned long)cur); rw_swap_page_sync(WRITE, entry, page); prev = entry; printk( "S" ); mark_swapfiles(prev, MARK_SWAP_SUSPEND); printk( "|\n" ); MDELAY(1000); return 0; }