lkml.org 
[lkml]   [2004]   [Jul]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[6/25] Merge pmdisk and swsusp

    ChangeSet 1.1848, 2004/07/17 10:07:17-07:00, mochel@digitalimplant.org

    [Power Mgmt] Consolidate code for allocating image pages in pmdisk and swsusp

    - Move helpers calc_order(), alloc_pagedir(), alloc_image_pages(),
    enough_free_mem(), and enough_swap() into swsusp.
    - Wrap them all with a new function - swsusp_alloc().
    - Fix up pmdisk to just call that.
    - Fix up suspend_prepare_image() to call that, instead of doing it inline.


    kernel/power/pmdisk.c | 161 +----------------------------------------
    kernel/power/swsusp.c | 196 +++++++++++++++++++++++++++++++++++---------------
    2 files changed, 143 insertions(+), 214 deletions(-)


    diff -Nru a/kernel/power/pmdisk.c b/kernel/power/pmdisk.c
    --- a/kernel/power/pmdisk.c 2004-07-17 14:51:37 -07:00
    +++ b/kernel/power/pmdisk.c 2004-07-17 14:51:37 -07:00
    @@ -350,138 +350,9 @@
    }


    -/**
    - * free_image_pages - Free each page allocated for snapshot.
    - */
    -
    -static void free_image_pages(void)
    -{
    - struct pbe * p;
    - int i;
    -
    - for (i = 0, p = pagedir_save; i < nr_copy_pages; i++, p++) {
    - ClearPageNosave(virt_to_page(p->address));
    - free_page(p->address);
    - }
    -}
    -
    -
    -/**
    - * free_pagedir - Free the page directory.
    - */
    -
    -static void free_pagedir(void)
    -{
    - free_image_pages();
    - free_pages((unsigned long)pagedir_save, pagedir_order);
    -}
    -
    -
    -static void calc_order(void)
    -{
    - int diff;
    - int order;
    -
    - order = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages));
    - nr_copy_pages += 1 << order;
    - do {
    - diff = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages)) - order;
    - if (diff) {
    - order += diff;
    - nr_copy_pages += 1 << diff;
    - }
    - } while(diff);
    - pagedir_order = order;
    -}
    -
    -
    -/**
    - * alloc_pagedir - Allocate the page directory.
    - *
    - * First, determine exactly how many contiguous pages we need,
    - * allocate them, then mark each 'unsavable'.
    - */
    -
    -static int alloc_pagedir(void)
    -{
    - calc_order();
    - pagedir_save = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD,
    - pagedir_order);
    - if(!pagedir_save)
    - return -ENOMEM;
    - memset(pagedir_save,0,(1 << pagedir_order) * PAGE_SIZE);
    - pagedir_nosave = pagedir_save;
    - return 0;
    -}
    -
    -
    -/**
    - * alloc_image_pages - Allocate pages for the snapshot.
    - *
    - */
    -
    -static int alloc_image_pages(void)
    -{
    - struct pbe * p;
    - int i;
    -
    - for (i = 0, p = pagedir_save; i < nr_copy_pages; i++, p++) {
    - p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
    - if(!p->address)
    - goto Error;
    - SetPageNosave(virt_to_page(p->address));
    - }
    - return 0;
    - Error:
    - do {
    - if (p->address)
    - free_page(p->address);
    - p->address = 0;
    - } while (p-- > pagedir_save);
    - return -ENOMEM;
    -}
    -
    -
    -/**
    - * enough_free_mem - Make sure we enough free memory to snapshot.
    - *
    - * Returns TRUE or FALSE after checking the number of available
    - * free pages.
    - */
    -
    -static int enough_free_mem(void)
    -{
    - if(nr_free_pages() < (nr_copy_pages + PAGES_FOR_IO)) {
    - pr_debug("pmdisk: Not enough free pages: Have %d\n",
    - nr_free_pages());
    - return 0;
    - }
    - return 1;
    -}
    -
    -
    -/**
    - * enough_swap - Make sure we have enough swap to save the image.
    - *
    - * Returns TRUE or FALSE after checking the total amount of swap
    - * space avaiable.
    - *
    - * FIXME: si_swapinfo(&i) returns all swap devices information.
    - * We should only consider resume_device.
    - */
    -
    -static int enough_swap(void)
    -{
    - struct sysinfo i;
    -
    - si_swapinfo(&i);
    - if (i.freeswap < (nr_copy_pages + PAGES_FOR_IO)) {
    - pr_debug("pmdisk: Not enough swap. Need %ld\n",i.freeswap);
    - return 0;
    - }
    - return 1;
    -}

    +extern int swsusp_alloc(void);
    +extern void free_suspend_pagedir(unsigned long);

    /**
    * pmdisk_suspend - Atomically snapshot the system.
    @@ -503,33 +374,11 @@
    return error;

    drain_local_pages();
    -
    - pagedir_nosave = NULL;
    pr_debug("pmdisk: Counting pages to copy.\n" );
    count_pages();
    -
    - pr_debug("pmdisk: (pages needed: %d + %d free: %d)\n",
    - nr_copy_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 = nr_copy_pages;
    - pagedir_order_check = pagedir_order;

    + error = swsusp_alloc();
    +
    /* During allocating of suspend pagedir, new cold pages may appear.
    * Kill them
    */
    @@ -931,7 +780,7 @@
    int pmdisk_free(void)
    {
    pr_debug( "Freeing prev allocated pagedir\n" );
    - free_pagedir();
    + free_suspend_pagedir((unsigned long)pagedir_save);
    return 0;
    }

    diff -Nru a/kernel/power/swsusp.c b/kernel/power/swsusp.c
    --- a/kernel/power/swsusp.c 2004-07-17 14:51:37 -07:00
    +++ b/kernel/power/swsusp.c 2004-07-17 14:51:37 -07:00
    @@ -594,7 +594,7 @@
    }
    }

    -static void free_suspend_pagedir(unsigned long this_pagedir)
    +void free_suspend_pagedir(unsigned long this_pagedir)
    {
    struct zone *zone;
    for_each_zone(zone) {
    @@ -604,36 +604,6 @@
    free_pages(this_pagedir, pagedir_order);
    }

    -static suspend_pagedir_t *create_suspend_pagedir(int nr_copy_pages)
    -{
    - int i;
    - suspend_pagedir_t *pagedir;
    - struct pbe *p;
    - struct page *page;
    -
    - pagedir_order = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages));
    -
    - p = pagedir = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD, pagedir_order);
    - if (!pagedir)
    - return NULL;
    -
    - page = virt_to_page(pagedir);
    - for(i=0; i < 1<<pagedir_order; i++)
    - SetPageNosave(page++);
    -
    - while(nr_copy_pages--) {
    - p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
    - if (!p->address) {
    - free_suspend_pagedir((unsigned long) pagedir);
    - return NULL;
    - }
    - SetPageNosave(virt_to_page(p->address));
    - p->orig_address = 0;
    - p++;
    - }
    - return pagedir;
    -}
    -
    static int prepare_suspend_processes(void)
    {
    sys_sync(); /* Syncing needs pdflushd, so do it before stopping processes */
    @@ -658,12 +628,145 @@
    printk("|\n");
    }

    -static int suspend_prepare_image(void)
    +
    +static void calc_order(void)
    +{
    + int diff;
    + int order;
    +
    + order = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages));
    + nr_copy_pages += 1 << order;
    + do {
    + diff = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages)) - order;
    + if (diff) {
    + order += diff;
    + nr_copy_pages += 1 << diff;
    + }
    + } while(diff);
    + pagedir_order = order;
    +}
    +
    +
    +/**
    + * alloc_pagedir - Allocate the page directory.
    + *
    + * First, determine exactly how many contiguous pages we need,
    + * allocate them, then mark each 'unsavable'.
    + */
    +
    +static int alloc_pagedir(void)
    +{
    + calc_order();
    + pagedir_save = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD,
    + pagedir_order);
    + if(!pagedir_save)
    + return -ENOMEM;
    + memset(pagedir_save,0,(1 << pagedir_order) * PAGE_SIZE);
    + pagedir_nosave = pagedir_save;
    + return 0;
    +}
    +
    +
    +/**
    + * alloc_image_pages - Allocate pages for the snapshot.
    + *
    + */
    +
    +static int alloc_image_pages(void)
    +{
    + struct pbe * p;
    + int i;
    +
    + for (i = 0, p = pagedir_save; i < nr_copy_pages; i++, p++) {
    + p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
    + if(!p->address)
    + goto Error;
    + SetPageNosave(virt_to_page(p->address));
    + }
    + return 0;
    + Error:
    + do {
    + if (p->address)
    + free_page(p->address);
    + p->address = 0;
    + } while (p-- > pagedir_save);
    + return -ENOMEM;
    +}
    +
    +
    +/**
    + * enough_free_mem - Make sure we enough free memory to snapshot.
    + *
    + * Returns TRUE or FALSE after checking the number of available
    + * free pages.
    + */
    +
    +static int enough_free_mem(void)
    +{
    + if(nr_free_pages() < (nr_copy_pages + PAGES_FOR_IO)) {
    + pr_debug("pmdisk: Not enough free pages: Have %d\n",
    + nr_free_pages());
    + return 0;
    + }
    + return 1;
    +}
    +
    +
    +/**
    + * enough_swap - Make sure we have enough swap to save the image.
    + *
    + * Returns TRUE or FALSE after checking the total amount of swap
    + * space avaiable.
    + *
    + * FIXME: si_swapinfo(&i) returns all swap devices information.
    + * We should only consider resume_device.
    + */
    +
    +static int enough_swap(void)
    {
    struct sysinfo i;
    - unsigned int nr_needed_pages = 0;
    +
    + si_swapinfo(&i);
    + if (i.freeswap < (nr_copy_pages + PAGES_FOR_IO)) {
    + pr_debug("pmdisk: Not enough swap. Need %ld\n",i.freeswap);
    + return 0;
    + }
    + return 1;
    +}
    +
    +int swsusp_alloc(void)
    +{
    + int error;
    +
    + pr_debug("suspend: (pages needed: %d + %d free: %d)\n",
    + nr_copy_pages,PAGES_FOR_IO,nr_free_pages());

    pagedir_nosave = NULL;
    + if (!enough_free_mem())
    + return -ENOMEM;
    +
    + if (!enough_swap())
    + return -ENOSPC;
    +
    + if ((error = alloc_pagedir())) {
    + pr_debug("suspend: Allocating pagedir failed.\n");
    + return error;
    + }
    + if ((error = alloc_image_pages())) {
    + pr_debug("suspend: Allocating image pages failed.\n");
    + free_suspend_pagedir((unsigned long)pagedir_save);
    + return error;
    + }
    +
    + nr_copy_pages_check = nr_copy_pages;
    + pagedir_order_check = pagedir_order;
    + return 0;
    +}
    +
    +static int suspend_prepare_image(void)
    +{
    + unsigned int nr_needed_pages = 0;
    +
    printk( "/critical section: ");
    #ifdef CONFIG_HIGHMEM
    printk( "handling highmem" );
    @@ -678,32 +781,9 @@
    drain_local_pages();
    nr_copy_pages = count_and_copy_data_pages(NULL);
    nr_needed_pages = nr_copy_pages + PAGES_FOR_IO;
    -
    - printk(" (pages needed: %d+%d=%d free: %d)\n",nr_copy_pages,PAGES_FOR_IO,nr_needed_pages,nr_free_pages());
    - if(nr_free_pages() < nr_needed_pages) {
    - printk(KERN_CRIT "%sCouldn't get enough free pages, on %d pages short\n",
    - name_suspend, nr_needed_pages-nr_free_pages());
    - root_swap = 0xFFFF;
    - return -ENOMEM;
    - }
    - si_swapinfo(&i); /* FIXME: si_swapinfo(&i) returns all swap devices information.
    - We should only consider resume_device. */
    - if (i.freeswap < nr_needed_pages) {
    - printk(KERN_CRIT "%sThere's not enough swap space available, on %ld pages short\n",
    - name_suspend, nr_needed_pages-i.freeswap);
    - return -ENOSPC;
    - }
    -
    - PRINTK( "Alloc pagedir\n" );
    - pagedir_save = pagedir_nosave = create_suspend_pagedir(nr_copy_pages);
    - if (!pagedir_nosave) {
    - /* Pagedir is big, one-chunk allocation. It is easily possible for this allocation to fail */
    - printk(KERN_CRIT "%sCouldn't allocate continuous pagedir\n", name_suspend);
    - return -ENOMEM;
    - }
    - nr_copy_pages_check = nr_copy_pages;
    - pagedir_order_check = pagedir_order;

    + swsusp_alloc();
    +
    drain_local_pages(); /* During allocating of suspend pagedir, new cold pages may appear. Kill them */
    if (nr_copy_pages != count_and_copy_data_pages(pagedir_nosave)) /* copy */
    BUG();
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2005-03-22 14:04    [W:0.042 / U:34.172 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site