lkml.org 
[lkml]   [2004]   [Sep]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectFYI: my current bigdiff
    Hi!

    This is my bigdiff. It is not for inclusion (I'll have to split it),
    but it contains some usefull code (I believe :-).

    Oh, it speeds up swsusp quite a lot.

    Pavel
    --
    When do you have heart between your knees?



    --- clean-mm/Documentation/power/swsusp.txt 2004-08-24 09:01:50.000000000 +0200
    +++ linux-mm/Documentation/power/swsusp.txt 2004-09-07 21:15:17.000000000 +0200
    @@ -20,26 +20,6 @@
    You need to append resume=/dev/your_swap_partition to kernel command
    line. Then you suspend by echo 4 > /proc/acpi/sleep.

    -Pavel's unreliable guide to swsusp mess
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    -
    -There are currently two versions of swap suspend in the kernel, the old
    -"Pavel's" version in kernel/power/swsusp.c and the new "Patrick's"
    -version in kernel/power/pmdisk.c. They provide the same functionality;
    -the old version looks ugly but was tested, while the new version looks
    -nicer but did not receive so much testing. echo 4 > /proc/acpi/sleep
    -calls the old version, echo disk > /sys/power/state calls the new one.
    -
    -[In the future, when the new version is stable enough, two things can
    -happen:
    -
    -* the new version is moved into swsusp.c, and swsusp is renamed to swap
    - suspend (Pavel prefers this)
    -
    -* pmdisk is kept as is and swsusp.c is removed from the kernel]
    -
    -
    -
    Article about goals and implementation of Software Suspend for Linux
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Author: G‚ábor Kuti
    @@ -75,10 +55,6 @@
    About the code

    Things to implement
    -- SMP support. I've done an SMP support but since I don't have access to a kind
    - of this one I cannot test it. Please SMP people test it. .. Tested it,
    - doesn't work. Had no time to figure out why. There is some mess with
    - interrupts AFAIK..
    - We should only make a copy of data related to kernel segment, since any
    process data won't be changed.
    - Should make more sanity checks. Or are these enough?
    @@ -90,11 +66,6 @@
    - We should not free pages at the beginning so aggressively, most of them
    go there anyway..

    -Drivers that need support
    -- pc_keyb -- perhaps we can wait for vojtech's input patches
    -- do IDE cdroms need some kind of support?
    -- IDE CD-RW -- how to deal with that?
    -
    Sleep states summary (thanx, Ducrot)
    ====================================

    @@ -109,7 +80,8 @@
    echo 4b > /proc/acpi/sleep # for suspend to disk via s4bios


    -FAQ:
    +Frequently Asked Questions
    +==========================

    Q: well, suspending a server is IMHO a really stupid thing,
    but... (Diego Zuccato):
    --- clean-mm/arch/i386/kernel/acpi/wakeup.S 2004-08-24 09:02:23.000000000 +0200
    +++ linux-mm/arch/i386/kernel/acpi/wakeup.S 2004-09-07 21:15:17.000000000 +0200
    @@ -11,8 +11,23 @@
    #
    # If physical address of wakeup_code is 0x12345, BIOS should call us with
    # cs = 0x1234, eip = 0x05
    -#
    +#

    +#define BEEP \
    + inb $97, %al; \
    + outb %al, $0x80; \
    + movb $3, %al; \
    + outb %al, $97; \
    + outb %al, $0x80; \
    + movb $-74, %al; \
    + outb %al, $67; \
    + outb %al, $0x80; \
    + movb $-119, %al; \
    + outb %al, $66; \
    + outb %al, $0x80; \
    + movb $15, %al; \
    + outb %al, $66;
    +
    ALIGN
    .align 4096
    ENTRY(wakeup_start)
    @@ -20,6 +35,7 @@
    wakeup_code_start = .
    .code16

    + BEEP
    movw $0xb800, %ax
    movw %ax,%fs
    movw $0x0e00 + 'L', %fs:(0x10)
    --- clean-mm/arch/i386/power/swsusp.S 2004-09-07 21:12:20.000000000 +0200
    +++ linux-mm/arch/i386/power/swsusp.S 2004-09-09 01:28:28.000000000 +0200
    @@ -31,7 +31,7 @@
    movl $swsusp_pg_dir-__PAGE_OFFSET,%ecx
    movl %ecx,%cr3

    - movl pagedir_nosave,%ebx
    + movl pagedir_nosave, %ebx
    xorl %eax, %eax
    xorl %edx, %edx
    .p2align 4,,7
    --- clean-mm/drivers/acpi/fan.c 2004-08-24 09:01:53.000000000 +0200
    +++ linux-mm/drivers/acpi/fan.c 2004-09-07 21:15:19.000000000 +0200
    @@ -94,10 +94,10 @@
    goto end;

    if (acpi_bus_get_power(fan->handle, &state))
    - goto end;
    -
    - p += sprintf(p, "status: %s\n",
    - !state?"on":"off");
    + p += sprintf(p, "status: ERROR\n");
    + else
    + p += sprintf(p, "status: %s\n",
    + !state?"on":"off");

    end:
    len = (p - page);
    --- clean-mm/drivers/acpi/sleep/proc.c 2004-08-24 09:03:14.000000000 +0200
    +++ linux-mm/drivers/acpi/sleep/proc.c 2004-09-07 21:15:19.000000000 +0200
    @@ -57,7 +57,8 @@
    int error = 0;

    if (count > sizeof(str) - 1)
    - goto Done;
    + return -EIO;
    +
    memset(str,0,sizeof(str));
    if (copy_from_user(str, buffer, count))
    return -EFAULT;
    @@ -65,17 +66,16 @@
    /* Check for S4 bios request */
    if (!strcmp(str,"4b")) {
    error = acpi_suspend(4);
    - goto Done;
    + return error ? error : count;
    }
    state = simple_strtoul(str, NULL, 0);
    #ifdef CONFIG_SOFTWARE_SUSPEND
    if (state == 4) {
    - software_suspend();
    - goto Done;
    + error = software_suspend();
    + return error ? error : count;
    }
    #endif
    error = acpi_suspend(state);
    - Done:
    return error ? error : count;
    }

    --- clean-mm/drivers/base/power/power.h 2004-08-24 09:01:51.000000000 +0200
    +++ linux-mm/drivers/base/power/power.h 2004-09-07 21:15:19.000000000 +0200
    @@ -1,5 +1,4 @@
    -
    -
    +/* FIXME: This needs explanation... */
    enum {
    DEVICE_PM_ON,
    DEVICE_PM1,
    --- clean-mm/drivers/char/keyboard.c 2004-09-07 21:12:22.000000000 +0200
    +++ linux-mm/drivers/char/keyboard.c 2004-09-07 21:15:19.000000000 +0200
    @@ -1076,6 +1076,23 @@
    sysrq_down = down;
    return;
    }
    + if (test_bit(KEY_LEFTALT, key_down) &&
    + test_bit(KEY_RIGHTALT, key_down) &&
    + test_bit(KEY_LEFTSHIFT, key_down) &&
    + test_bit(KEY_RIGHTSHIFT, key_down) &&
    + down && !rep) {
    + handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty);
    +#ifdef CONFIG_KGDB_SYSRQ
    + sysrq_down = 0; /* in case we miss the "up" event */
    +#endif
    + return;
    + }
    +
    + if (down)
    + set_bit(keycode, key_down);
    + else
    + clear_bit(keycode, key_down);
    +
    if (sysrq_down && down && !rep) {
    handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty);
    #ifdef CONFIG_KGDB_SYSRQ
    @@ -1111,11 +1128,6 @@
    raw_mode = 1;
    }

    - if (down)
    - set_bit(keycode, key_down);
    - else
    - clear_bit(keycode, key_down);
    -
    if (rep && (!vc_kbd_mode(kbd, VC_REPEAT) || (tty &&
    (!L_ECHO(tty) && tty->driver->chars_in_buffer(tty))))) {
    /*
    --- clean-mm/drivers/video/aty/radeon_pm.c 2004-08-24 09:03:18.000000000 +0200
    +++ linux-mm/drivers/video/aty/radeon_pm.c 2004-09-07 21:15:20.000000000 +0200
    @@ -871,7 +871,8 @@
    agp_enable(0);
    #endif

    - fb_set_suspend(info, 1);
    + if (system_state != SYSTEM_SNAPSHOT)
    + fb_set_suspend(info, 1);

    if (!(info->flags & FBINFO_HWACCEL_DISABLED)) {
    /* Make sure engine is reset */
    @@ -880,12 +881,14 @@
    radeon_engine_idle();
    }

    - /* Blank display and LCD */
    - radeonfb_blank(VESA_POWERDOWN, info);
    -
    - /* Sleep */
    - rinfo->asleep = 1;
    - rinfo->lock_blank = 1;
    + if (system_state != SYSTEM_SNAPSHOT) {
    + /* Blank display and LCD */
    + radeonfb_blank(VESA_POWERDOWN, info);
    +
    + /* Sleep */
    + rinfo->asleep = 1;
    + rinfo->lock_blank = 1;
    + }

    /* Suspend the chip to D2 state when supported
    */
    --- clean-mm/fs/bio.c 2004-09-07 21:12:30.000000000 +0200
    +++ linux-mm/fs/bio.c 2004-09-07 21:15:20.000000000 +0200
    @@ -143,7 +143,7 @@

    bio = mempool_alloc(bio_pool, gfp_mask);
    if (unlikely(!bio))
    - goto out;
    + return NULL;

    bio_init(bio);

    @@ -157,13 +157,11 @@
    noiovec:
    bio->bi_io_vec = bvl;
    bio->bi_destructor = bio_destructor;
    -out:
    return bio;
    }

    mempool_free(bio, bio_pool);
    - bio = NULL;
    - goto out;
    + return NULL;
    }

    /**
    --- clean-mm/include/linux/page-flags.h 2004-09-07 21:12:33.000000000 +0200
    +++ linux-mm/include/linux/page-flags.h 2004-09-07 21:15:21.000000000 +0200
    @@ -75,7 +75,7 @@
    #define PG_swapcache 16 /* Swap page: swp_entry_t in private */
    #define PG_mappedtodisk 17 /* Has blocks allocated on-disk */
    #define PG_reclaim 18 /* To be reclaimed asap */
    -
    +#define PG_nosave_free 19 /* Page is free and should not be written */

    /*
    * Global page accounting. One instance per CPU. Only unsigned longs are
    @@ -278,6 +278,10 @@
    #define ClearPageNosave(page) clear_bit(PG_nosave, &(page)->flags)
    #define TestClearPageNosave(page) test_and_clear_bit(PG_nosave, &(page)->flags)

    +#define PageNosaveFree(page) test_bit(PG_nosave_free, &(page)->flags)
    +#define SetPageNosaveFree(page) set_bit(PG_nosave_free, &(page)->flags)
    +#define ClearPageNosaveFree(page) clear_bit(PG_nosave_free, &(page)->flags)
    +
    #define PageMappedToDisk(page) test_bit(PG_mappedtodisk, &(page)->flags)
    #define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags)
    #define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags)
    --- clean-mm/include/linux/suspend.h 2004-09-07 21:12:33.000000000 +0200
    +++ linux-mm/include/linux/suspend.h 2004-09-07 21:15:22.000000000 +0200
    @@ -31,6 +31,7 @@

    /* mm/page_alloc.c */
    extern void drain_local_pages(void);
    +extern void mark_free_pages(struct zone *zone);

    /* kernel/power/swsusp.c */
    extern int software_suspend(void);
    --- clean-mm/kernel/power/disk.c 2004-09-07 21:12:33.000000000 +0200
    +++ linux-mm/kernel/power/disk.c 2004-09-08 22:47:41.000000000 +0200
    @@ -71,7 +71,7 @@
    machine_halt();
    /* Valid image is on the disk, if we continue we risk serious data corruption
    after resume. */
    - printk("Please power me down manually\n");
    + printk(KERN_CRIT "Please power me down manually\n");
    while(1);
    return 0;
    }
    @@ -91,10 +91,20 @@

    static void free_some_memory(void)
    {
    - printk("Freeing memory: ");
    - while (shrink_all_memory(10000))
    - printk(".");
    - printk("|\n");
    + unsigned int i = 0;
    + unsigned int tmp;
    + unsigned long pages = 0;
    + char *p = "-\\|/";
    +
    + printk("Freeing memory... ");
    + while ((tmp = shrink_all_memory(10000))) {
    + pages += tmp;
    + printk("\b%c", p[i]);
    + i++;
    + if (i > 3)
    + i = 0;
    + }
    + printk("\bdone (%li pages freed)\n", pages);
    }


    @@ -167,6 +177,7 @@
    {
    int error;

    + system_state = SYSTEM_SNAPSHOT;
    if ((error = prepare()))
    return error;

    --- clean-mm/kernel/power/swsusp.c 2004-09-07 21:12:33.000000000 +0200
    +++ linux-mm/kernel/power/swsusp.c 2004-09-09 08:56:20.000000000 +0200
    @@ -74,11 +74,9 @@
    /* References to section boundaries */
    extern char __nosave_begin, __nosave_end;

    -extern int is_head_of_free_region(struct page *);
    -
    /* Variables to be preserved over suspend */
    -int pagedir_order_check;
    -int nr_copy_pages_check;
    +static int pagedir_order_check;
    +static int nr_copy_pages_check;

    extern char resume_file[];
    static dev_t resume_device;
    @@ -99,8 +97,8 @@
    MMU hardware.
    */
    suspend_pagedir_t *pagedir_nosave __nosavedata = NULL;
    -suspend_pagedir_t *pagedir_save;
    -int pagedir_order __nosavedata = 0;
    +static suspend_pagedir_t *pagedir_save;
    +static int pagedir_order __nosavedata = 0;

    #define SWSUSP_SIG "S1SUSPEND"

    @@ -119,9 +117,6 @@
    */
    #define PAGES_FOR_IO 512

    -static const char name_suspend[] = "Suspend Machine: ";
    -static const char name_resume[] = "Resume Machine: ";
    -
    /*
    * Saving part...
    */
    @@ -141,10 +136,10 @@
    rw_swap_page_sync(READ,
    swp_entry(root_swap, 0),
    virt_to_page((unsigned long)&swsusp_header));
    - if (!memcmp("SWAP-SPACE",swsusp_header.sig,10) ||
    - !memcmp("SWAPSPACE2",swsusp_header.sig,10)) {
    - memcpy(swsusp_header.orig_sig,swsusp_header.sig,10);
    - memcpy(swsusp_header.sig,SWSUSP_SIG,10);
    + if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) ||
    + !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) {
    + memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
    + memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
    swsusp_header.swsusp_info = prev;
    error = rw_swap_page_sync(WRITE,
    swp_entry(root_swap, 0),
    @@ -265,9 +260,10 @@


    /**
    - * free_data - Free the swap entries used by the saved image.
    + * data_free - Free the swap entries used by the saved image.
    *
    * Walk the list of used swap entries and free each one.
    + * This is only used for cleanup when suspend fails.
    */

    static void data_free(void)
    @@ -287,7 +283,7 @@


    /**
    - * write_data - Write saved image to swap.
    + * data_write - Write saved image to swap.
    *
    * Walk the list of pages in the image and sync each one to swap.
    */
    @@ -296,15 +292,19 @@
    {
    int error = 0;
    int i;
    -
    - printk( "Writing data to swap (%d pages): ", nr_copy_pages );
    + unsigned int mod = nr_copy_pages / 100;
    +
    + if (!mod)
    + mod = 1;
    +
    + printk( "Writing data to swap (%d pages)... ", nr_copy_pages );
    for (i = 0; i < nr_copy_pages && !error; i++) {
    - if (!(i%100))
    - printk( "." );
    + if (!(i%mod))
    + printk( "\b\b\b\b%3d%%", i / mod );
    error = write_page((pagedir_nosave+i)->address,
    &((pagedir_nosave+i)->swap_address));
    }
    - printk(" %d Pages done.\n",i);
    + printk("\b\b\b\bdone\n");
    return error;
    }

    @@ -351,15 +351,16 @@
    }

    /**
    - * free_pagedir - Free pages used by the page directory.
    + * free_pagedir_entries - Free pages used by the page directory.
    + *
    + * This is used during suspend for error recovery.
    */

    static void free_pagedir_entries(void)
    {
    - int num = swsusp_info.pagedir_pages;
    int i;

    - for (i = 0; i < num; i++)
    + for (i = 0; i < swsusp_info.pagedir_pages; i++)
    swap_free(swsusp_info.pagedir[i]);
    }

    @@ -379,7 +380,7 @@
    swsusp_info.pagedir_pages = n;
    printk( "Writing pagedir (%d pages)\n", n);
    for (i = 0; i < n && !error; i++, addr += PAGE_SIZE)
    - error = write_page(addr,&swsusp_info.pagedir[i]);
    + error = write_page(addr, &swsusp_info.pagedir[i]);
    return error;
    }

    @@ -423,12 +424,12 @@
    static int save_highmem_zone(struct zone *zone)
    {
    unsigned long zone_pfn;
    + mark_free_pages(zone);
    for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
    struct page *page;
    struct highmem_page *save;
    void *kaddr;
    unsigned long pfn = zone_pfn + zone->zone_start_pfn;
    - int chunk_size;

    if (!(pfn%1000))
    printk(".");
    @@ -445,11 +446,8 @@
    printk("highmem reserved page?!\n");
    continue;
    }
    - if ((chunk_size = is_head_of_free_region(page))) {
    - pfn += chunk_size - 1;
    - zone_pfn += chunk_size - 1;
    + if (PageNosaveFree(page))
    continue;
    - }
    save = kmalloc(sizeof(struct highmem_page), GFP_ATOMIC);
    if (!save)
    return -ENOMEM;
    @@ -528,14 +526,11 @@
    static int saveable(struct zone * zone, unsigned long * zone_pfn)
    {
    unsigned long pfn = *zone_pfn + zone->zone_start_pfn;
    - unsigned long chunk_size;
    struct page * page;

    if (!pfn_valid(pfn))
    return 0;

    - if (!(pfn%1000))
    - printk(".");
    page = pfn_to_page(pfn);
    BUG_ON(PageReserved(page) && PageNosave(page));
    if (PageNosave(page))
    @@ -544,10 +539,8 @@
    pr_debug("[nosave pfn 0x%lx]", pfn);
    return 0;
    }
    - if ((chunk_size = is_head_of_free_region(page))) {
    - *zone_pfn += chunk_size - 1;
    + if (PageNosaveFree(page))
    return 0;
    - }

    return 1;
    }
    @@ -561,6 +554,7 @@

    for_each_zone(zone) {
    if (!is_highmem(zone)) {
    + mark_free_pages(zone);
    for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
    nr_copy_pages += saveable(zone, &zone_pfn);
    }
    @@ -575,50 +569,20 @@
    struct pbe * pbe = pagedir_nosave;

    for_each_zone(zone) {
    - if (!is_highmem(zone))
    - for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
    - if (saveable(zone, &zone_pfn)) {
    - struct page * page;
    - page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
    - pbe->orig_address = (long) page_address(page);
    - /* copy_page is no usable for copying task structs. */
    - memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE);
    - pbe++;
    - }
    - }
    - }
    -}
    -
    -
    -static void free_suspend_pagedir_zone(struct zone *zone, unsigned long pagedir)
    -{
    - unsigned long zone_pfn, pagedir_end, pagedir_pfn, pagedir_end_pfn;
    - pagedir_end = pagedir + (PAGE_SIZE << pagedir_order);
    - pagedir_pfn = __pa(pagedir) >> PAGE_SHIFT;
    - pagedir_end_pfn = __pa(pagedir_end) >> PAGE_SHIFT;
    - for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
    - struct page *page;
    - unsigned long pfn = zone_pfn + zone->zone_start_pfn;
    - if (!pfn_valid(pfn))
    - continue;
    - page = pfn_to_page(pfn);
    - if (!TestClearPageNosave(page))
    - continue;
    - else if (pfn >= pagedir_pfn && pfn < pagedir_end_pfn)
    + if (is_highmem(zone))
    continue;
    - __free_page(page);
    - }
    -}
    -
    -void swsusp_free(void)
    -{
    - unsigned long p = (unsigned long)pagedir_save;
    - struct zone *zone;
    - for_each_zone(zone) {
    - if (!is_highmem(zone))
    - free_suspend_pagedir_zone(zone, p);
    + mark_free_pages(zone);
    + for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
    + if (saveable(zone, &zone_pfn)) {
    + struct page * page;
    + page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
    + pbe->orig_address = (long) page_address(page);
    + /* copy_page is not usable for copying task structs. */
    + memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE);
    + pbe++;
    + }
    + }
    }
    - free_pages(p, pagedir_order);
    }


    @@ -668,8 +632,8 @@
    /**
    * alloc_pagedir - Allocate the page directory.
    *
    - * First, determine exactly how many contiguous pages we need,
    - * allocate them, then mark each 'unsavable'.
    + * First, determine exactly how many contiguous pages we need and
    + * allocate them.
    */

    static int alloc_pagedir(void)
    @@ -684,6 +648,24 @@
    return 0;
    }

    +/**
    + * free_image_pages - Free pages allocated for snapshot
    + */
    +
    +static void free_image_pages(void)
    +{
    + struct pbe * p;
    + int i;
    +
    + p = pagedir_save;
    + for (i = 0, p = pagedir_save; i < nr_copy_pages; i++, p++) {
    + if (p->address) {
    + ClearPageNosave(virt_to_page(p->address));
    + free_page(p->address);
    + p->address = 0;
    + }
    + }
    +}

    /**
    * alloc_image_pages - Allocate pages for the snapshot.
    @@ -697,18 +679,19 @@

    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;
    + if (!p->address)
    + return -ENOMEM;
    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;
    +}
    +
    +void swsusp_free(void)
    +{
    + BUG_ON(PageNosave(virt_to_page(pagedir_save)));
    + BUG_ON(PageNosaveFree(virt_to_page(pagedir_save)));
    + free_image_pages();
    + free_pages((unsigned long) pagedir_save, pagedir_order);
    }


    @@ -721,7 +704,7 @@

    static int enough_free_mem(void)
    {
    - if(nr_free_pages() < (nr_copy_pages + PAGES_FOR_IO)) {
    + if (nr_free_pages() < (nr_copy_pages + PAGES_FOR_IO)) {
    pr_debug("swsusp: Not enough free pages: Have %d\n",
    nr_free_pages());
    return 0;
    @@ -757,7 +740,7 @@
    int error;

    pr_debug("suspend: (pages needed: %d + %d free: %d)\n",
    - nr_copy_pages,PAGES_FOR_IO,nr_free_pages());
    + nr_copy_pages, PAGES_FOR_IO, nr_free_pages());

    pagedir_nosave = NULL;
    if (!enough_free_mem())
    @@ -788,7 +771,7 @@

    pr_debug("swsusp: critical section: \n");
    if (save_highmem()) {
    - printk(KERN_CRIT "%sNot enough free pages for highmem\n", name_suspend);
    + printk(KERN_CRIT "Suspend machine: Not enough free pages for highmem\n");
    return -ENOMEM;
    }

    @@ -872,6 +855,7 @@

    /* Even mappings of "global" things (vmalloc) need to be fixed */
    __flush_tlb_global();
    + wbinvd(); /* Nigel says wbinvd here is good idea... */
    return 0;
    }

    @@ -907,8 +891,8 @@
    int i;
    unsigned long addre = addr + (PAGE_SIZE<<order);

    - for(i=0; i < nr_copy_pages; i++)
    - if((pagedir+i)->orig_address >= addr &&
    + for (i=0; i < nr_copy_pages; i++)
    + if ((pagedir+i)->orig_address >= addr &&
    (pagedir+i)->orig_address < addre)
    return 1;

    @@ -950,9 +934,9 @@

    printk("Relocating pagedir ");

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

    while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order)) != NULL) {
    @@ -994,24 +978,14 @@

    static atomic_t io_done = ATOMIC_INIT(0);

    -static void start_io(void)
    -{
    - atomic_set(&io_done,1);
    -}
    -
    static int end_io(struct bio * bio, unsigned int num, int err)
    {
    - atomic_set(&io_done,0);
    + if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
    + panic("I/O error reading memory image");
    + atomic_set(&io_done, 0);
    return 0;
    }

    -static void wait_io(void)
    -{
    - while(atomic_read(&io_done))
    - io_schedule();
    -}
    -
    -
    static struct block_device * resume_bdev;

    /**
    @@ -1030,7 +1004,7 @@
    int error = 0;
    struct bio * bio;

    - bio = bio_alloc(GFP_ATOMIC,1);
    + bio = bio_alloc(GFP_ATOMIC, 1);
    if (!bio)
    return -ENOMEM;
    bio->bi_sector = page_off * (PAGE_SIZE >> 9);
    @@ -1046,9 +1020,12 @@

    if (rw == WRITE)
    bio_set_pages_dirty(bio);
    - start_io();
    +
    + atomic_set(&io_done, 1);
    submit_bio(rw | (1 << BIO_RW_SYNC), bio);
    - wait_io();
    + while (atomic_read(&io_done))
    + yield();
    +
    Done:
    bio_put(bio);
    return error;
    @@ -1056,12 +1033,12 @@

    int bio_read_page(pgoff_t page_off, void * page)
    {
    - return submit(READ,page_off,page);
    + return submit(READ, page_off, page);
    }

    int bio_write_page(pgoff_t page_off, void * page)
    {
    - return submit(WRITE,page_off,page);
    + return submit(WRITE, page_off, page);
    }

    /*
    @@ -1104,6 +1081,7 @@
    return -EPERM;
    }
    nr_copy_pages = swsusp_info.image_pages;
    + pagedir_order = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages));
    return error;
    }

    @@ -1111,16 +1089,16 @@
    {
    int error;

    - memset(&swsusp_header,0,sizeof(swsusp_header));
    - if ((error = bio_read_page(0,&swsusp_header)))
    + memset(&swsusp_header, 0, sizeof(swsusp_header));
    + if ((error = bio_read_page(0, &swsusp_header)))
    return error;
    - if (!memcmp(SWSUSP_SIG,swsusp_header.sig,10)) {
    - memcpy(swsusp_header.sig,swsusp_header.orig_sig,10);
    + if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) {
    + memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10);

    /*
    * Reset swap signature now.
    */
    - error = bio_write_page(0,&swsusp_header);
    + error = bio_write_page(0, &swsusp_header);
    } else {
    pr_debug(KERN_ERR "swsusp: Suspend partition has wrong signature?\n");
    return -EINVAL;
    @@ -1130,17 +1108,6 @@
    return error;
    }

    -
    -int __init verify(void)
    -{
    - int error;
    -
    - if (!(error = check_sig()))
    - error = check_header();
    - return error;
    -}
    -
    -
    /**
    * swsusp_read_data - Read image pages from swap.
    *
    @@ -1153,14 +1120,18 @@
    struct pbe * p;
    int error;
    int i;
    -
    + int mod = nr_copy_pages / 100;
    +
    + if (!mod)
    + mod = 1;
    +
    if ((error = swsusp_pagedir_relocate()))
    return error;

    - printk( "Reading image data (%d pages): ", nr_copy_pages );
    + printk( "Reading image data (%d pages): ", nr_copy_pages );
    for(i = 0, p = pagedir_nosave; i < nr_copy_pages && !error; i++, p++) {
    - if (!(i%100))
    - printk( "." );
    + if (!(i%mod))
    + printk( "\b\b\b\b%3d%%", i / mod );
    error = bio_read_page(swp_offset(p->swap_address),
    (void *)p->address);
    }
    @@ -1177,9 +1148,7 @@
    int i, n = swsusp_info.pagedir_pages;
    int error = 0;

    - pagedir_order = get_bitmask_order(n);
    -
    - addr =__get_free_pages(GFP_ATOMIC, pagedir_order);
    + addr = __get_free_pages(GFP_ATOMIC, pagedir_order);
    if (!addr)
    return -ENOMEM;
    pagedir_nosave = (struct pbe *)addr;
    @@ -1194,7 +1163,7 @@
    error = -EFAULT;
    }
    if (error)
    - free_pages((unsigned long)pagedir_nosave,pagedir_order);
    + free_pages((unsigned long)pagedir_nosave, pagedir_order);
    return error;
    }

    @@ -1202,13 +1171,14 @@
    {
    int error = 0;

    - if ((error = verify()))
    + if ((error = check_sig()))
    + return error;
    + if ((error = check_header()))
    return error;
    if ((error = read_pagedir()))
    return error;
    - if ((error = data_read())) {
    - free_pages((unsigned long)pagedir_nosave,pagedir_order);
    - }
    + if ((error = data_read()))
    + free_pages((unsigned long)pagedir_nosave, pagedir_order);
    return error;
    }

    --- clean-mm/mm/page_alloc.c 2004-09-07 21:12:33.000000000 +0200
    +++ linux-mm/mm/page_alloc.c 2004-09-07 21:15:23.000000000 +0200
    @@ -437,26 +437,30 @@
    #endif /* CONFIG_PM || CONFIG_HOTPLUG_CPU */

    #ifdef CONFIG_PM
    -int is_head_of_free_region(struct page *page)
    +
    +void mark_free_pages(struct zone *zone)
    {
    - struct zone *zone = page_zone(page);
    - unsigned long flags;
    + unsigned long zone_pfn, flags;
    int order;
    struct list_head *curr;

    - /*
    - * Should not matter as we need quiescent system for
    - * suspend anyway, but...
    - */
    + if (!zone->spanned_pages)
    + return;
    +
    spin_lock_irqsave(&zone->lock, flags);
    + for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
    + ClearPageNosaveFree(pfn_to_page(zone_pfn + zone->zone_start_pfn));
    +
    for (order = MAX_ORDER - 1; order >= 0; --order)
    - list_for_each(curr, &zone->free_area[order].free_list)
    - if (page == list_entry(curr, struct page, lru)) {
    - spin_unlock_irqrestore(&zone->lock, flags);
    - return 1 << order;
    - }
    + list_for_each(curr, &zone->free_area[order].free_list) {
    + unsigned long start_pfn, i;
    +
    + start_pfn = page_to_pfn(list_entry(curr, struct page, lru));
    +
    + for (i=0; i < (1<<order); i++)
    + SetPageNosaveFree(pfn_to_page(start_pfn+i));
    + }
    spin_unlock_irqrestore(&zone->lock, flags);
    - return 0;
    }

    /*
    -
    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:06    [W:0.069 / U:89.412 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site