Exemple #1
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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
}
Exemple #6
0
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;
}
Exemple #7
0
/**
 *    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;
}