void do_magic_suspend_2(void) { int is_problem; read_swapfiles(); is_problem = suspend_prepare_image(); spin_unlock_irq(&suspend_pagedir_lock); if (!is_problem) { kernel_fpu_end(); /* save_processor_state() does kernel_fpu_begin, and we need to revert it in order to pass in_atomic() checks */ BUG_ON(in_atomic()); suspend_save_image(); suspend_power_down(); /* FIXME: if suspend_power_down is commented out, console is lost after few suspends ?! */ } printk(KERN_EMERG "%sSuspend failed, trying to recover...\n", name_suspend); MDELAY(1000); /* So user can wait and report us messages if armageddon comes :-) */ barrier(); mb(); spin_lock_irq(&suspend_pagedir_lock); /* Done to disable interrupts */ mdelay(1000); free_pages((unsigned long) pagedir_nosave, pagedir_order); spin_unlock_irq(&suspend_pagedir_lock); mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME); }
static int write_suspend_image(void) { int error; swp_entry_t prev = { 0 }; init_header(); if ((error = write_data())) goto FreeData; if ((error = write_pagedir())) goto FreePagedir; if ((error = write_header(&prev))) goto FreePagedir; error = mark_swapfiles(prev); Done: return error; FreePagedir: free_pagedir_entries(); FreeData: free_data(); goto Done; }
static int close_swap(void) { swp_entry_t entry; int error; error = write_page((unsigned long)&swsusp_info,&entry); if (!error) { printk( "S" ); error = mark_swapfiles(entry); printk( "|\n" ); } return error; }
int swsusp_write(unsigned int flags) { struct swap_map_handle handle; struct snapshot_handle snapshot; struct swsusp_info *header; int error; error = swsusp_swap_check(); if (error) { printk(KERN_ERR "PM: Cannot find swap device, try " "swapon -a.\n"); return error; } memset(&snapshot, 0, sizeof(struct snapshot_handle)); error = snapshot_read_next(&snapshot, PAGE_SIZE); if (error < PAGE_SIZE) { if (error >= 0) error = -EFAULT; goto out; } header = (struct swsusp_info *)data_of(snapshot); if (!enough_swap(header->pages)) { printk(KERN_ERR "PM: Not enough free swap\n"); error = -ENOSPC; goto out; } error = get_swap_writer(&handle); if (!error) { sector_t start = handle.cur_swap; error = swap_write_page(&handle, header, NULL); if (!error) error = save_image(&handle, &snapshot, header->pages - 1); if (!error) { flush_swap_writer(&handle); printk(KERN_INFO "PM: S"); error = mark_swapfiles(start, flags); printk("|\n"); } } if (error) free_all_swap_pages(root_swap); release_swap_writer(&handle); out: swsusp_close(FMODE_WRITE); return error; }
void do_magic_resume_2(void) { BUG_ON (nr_copy_pages_check != nr_copy_pages); BUG_ON (pagedir_order_check != pagedir_order); __flush_tlb_global(); /* Even mappings of "global" things (vmalloc) need to be fixed */ PRINTK( "Freeing prev allocated pagedir\n" ); free_suspend_pagedir((unsigned long) pagedir_save); spin_unlock_irq(&suspend_pagedir_lock); drivers_resume(RESUME_ALL_PHASES); PRINTK( "Fixing swap signatures... " ); mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME); PRINTK( "ok\n" ); #ifdef SUSPEND_CONSOLE update_screen(fg_console); /* Hmm, is this the problem? */ #endif }
int swsusp_write(void) { struct swap_map_handle handle; struct snapshot_handle snapshot; struct swsusp_info *header; int error; if ((error = swsusp_swap_check())) { printk(KERN_ERR "swsusp: Cannot find swap device, try swapon -a.\n"); return error; } memset(&snapshot, 0, sizeof(struct snapshot_handle)); error = snapshot_read_next(&snapshot, PAGE_SIZE); if (error < PAGE_SIZE) return error < 0 ? error : -EFAULT; header = (struct swsusp_info *)data_of(snapshot); if (!enough_swap(header->pages)) { printk(KERN_ERR "swsusp: Not enough free swap\n"); return -ENOSPC; } error = get_swap_writer(&handle); if (!error) { unsigned long start = handle.cur_swap; error = swap_write_page(&handle, header); if (!error) error = save_image(&handle, &snapshot, header->pages - 1); if (!error) { flush_swap_writer(&handle); printk("S"); error = mark_swapfiles(swp_entry(root_swap, start)); printk("|\n"); } } if (error) free_all_swap_pages(root_swap, handle.bitmap); release_swap_writer(&handle); 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; }