Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
static int __init swsusp_pagedir_relocate(void)
{
	/*
	 * We have to avoid recursion (not to overflow kernel stack),
	 * and that's why code looks pretty cryptic 
	 */
	suspend_pagedir_t *old_pagedir = pagedir_nosave;
	void **eaten_memory = NULL;
	void **c = eaten_memory, *m, *f;
	int ret = 0;
	struct zone *zone;
	int i;
	struct pbe *p;
	unsigned long zone_pfn;

	printk("Relocating pagedir ");

	/* Set page flags */

	for_each_zone(zone) {
        	for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
                	SetPageNosaveFree(pfn_to_page(zone_pfn +
					zone->zone_start_pfn));
	}

	/* Clear orig address */

	for(i = 0, p = pagedir_nosave; i < nr_copy_pages; i++, p++) {
		ClearPageNosaveFree(virt_to_page(p->orig_address));
	}

	if (!does_collide_order((unsigned long)old_pagedir, pagedir_order)) {
		printk("not necessary\n");
		return check_pagedir();
	}

	while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order)) != NULL) {
		if (!does_collide_order((unsigned long)m, pagedir_order))
			break;
		eaten_memory = m;
		printk( "." ); 
		*eaten_memory = c;
		c = eaten_memory;
	}

	if (!m) {
		printk("out of memory\n");
		ret = -ENOMEM;
	} else {
		pagedir_nosave =
			memcpy(m, old_pagedir, PAGE_SIZE << pagedir_order);
	}

	c = eaten_memory;
	while (c) {
		printk(":");
		f = c;
		c = *c;
		free_pages((unsigned long)f, pagedir_order);
	}
	if (ret)
		return ret;
	printk("|\n");
	return check_pagedir();
}