int pmdisk_suspend(void) { int error = 0; if ((error = read_swapfiles())) return error; drain_local_pages(); pm_pagedir_nosave = NULL; pr_debug("pmdisk: Counting pages to copy.\n" ); count_pages(); pr_debug("pmdisk: (pages needed: %d + %d free: %d)\n", pmdisk_pages,PAGES_FOR_IO,nr_free_pages()); if (!enough_free_mem()) return -ENOMEM; if (!enough_swap()) return -ENOSPC; if ((error = alloc_pagedir())) { pr_debug("pmdisk: Allocating pagedir failed.\n"); return error; } if ((error = alloc_image_pages())) { pr_debug("pmdisk: Allocating image pages failed.\n"); free_pagedir(); return error; } nr_copy_pages_check = pmdisk_pages; pagedir_order_check = pagedir_order; /* During allocating of suspend pagedir, new cold pages may appear. * Kill them */ drain_local_pages(); /* copy */ copy_pages(); /* * End of critical section. From now on, we can write to memory, * but we should not touch disk. This specially means we must _not_ * touch swap space! Except we must write out our image of course. */ pr_debug("pmdisk: %d pages copied\n", pmdisk_pages ); return 0; }
static struct pbe * alloc_pagedir(unsigned nr_pages) { unsigned num; struct pbe *pblist, *pbe; if (!nr_pages) return NULL; pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages); pblist = (struct pbe *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD); for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages; pbe = pbe->next, num += PBES_PER_PAGE) { pbe += PB_PAGE_SKIP; pbe->next = (struct pbe *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD); } if (!pbe) { /* get_zeroed_page() failed */ free_pagedir(pblist); pblist = NULL; } return pblist; }
struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask, int safe_needed) { unsigned int num; struct pbe *pblist, *pbe; if (!nr_pages) return NULL; pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages); pblist = alloc_image_page(gfp_mask, safe_needed); /* FIXME: rewrite this ugly loop */ for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages; pbe = pbe->next, num += PBES_PER_PAGE) { pbe += PB_PAGE_SKIP; pbe->next = alloc_image_page(gfp_mask, safe_needed); } if (!pbe) { /* get_zeroed_page() failed */ free_pagedir(pblist); pblist = NULL; } return pblist; }
int pmdisk_free(void) { pr_debug( "Freeing prev allocated pagedir\n" ); free_pagedir(); return 0; }