| From: |
| Nigel Cunningham <ncunningham@clear.net.nz> |
| To: |
| swsusp-devel <swsusp-devel@lists.sourceforge.net> |
| Subject: |
| [Swsusp-devel] Announce: rc8. |
| Date: |
| Tue, 02 Sep 2003 22:13:02 +1200 |
Hi all.
Here's another set of bug fixes. If you try to stress test this (as I'm
sure Michael will, helpful man that he is!), you will notice that it
only tries to freeze processes once before aborting. This is an intended
change, not a typo: I'm going for freezing them all first time, every
time, and therefore want to see reports on what fails. I'll almost
certainly put it back to 3, but for the moment I want to see those
reports please.
Other changes in this version:
- Further work on improving freezing and properly blocking I/O when
suspending (still getting the later right).
- Misc cleanups
- Removed old synchronous I/O functions: All I/O done through one method
now. Synchronous achieve by starting async I/O and then waiting till
it's done.
- Removed duplicated lines in code for aborting writing pagedir and
suspend header. This is known to still be broken, but you'd need very
bad timing or to actively debug it to trigger this bug.
- Fixed a bug in compressed image support that caused an oops on my
machine, perhaps the cause of hangs for others.
- Handle stopped tasks properly - ignore them instead of trying to
refrigerate them.
- Hang at thawing processes fixed, I hope.
Known bugs still to address:
- Michael's cleanup I/O?
- Michael's ocassional free range pages bug - to be investigated.
- Nigel: Ocassional memory pool bug - to be investigated.
Regards,
Nigel
--
Nigel Cunningham
495 St Georges Road South, Hastings 4201, New Zealand
You see, at just the right time, when we were still powerless,
Christ died for the ungodly.
-- Romans 5:6, NIV.
diff -ruN swsusp-1.1-rc7/drivers/block/ll_rw_blk.c swsusp-1.1-rc8/drivers/block/ll_rw_blk.c
--- swsusp-1.1-rc7/drivers/block/ll_rw_blk.c 2003-09-02 22:00:40.000000000 +1200
+++ swsusp-1.1-rc8/drivers/block/ll_rw_blk.c 2003-09-02 22:00:42.000000000 +1200
@@ -640,6 +640,10 @@
if (blk_oversized_queue(q) || q->rq.count == 0) {
__generic_unplug_device(q);
spin_unlock_irq(&io_request_lock);
+#ifdef CONFIG_SOFTWARE_SUSPEND
+ if (unlikely(current->flags & PF_FREEZE))
+ refrigerator(PF_IOTHREAD);
+#endif
schedule();
spin_lock_irq(&io_request_lock);
}
diff -ruN swsusp-1.1-rc7/drivers/ide/ide-io.c swsusp-1.1-rc8/drivers/ide/ide-io.c
--- swsusp-1.1-rc7/drivers/ide/ide-io.c 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/drivers/ide/ide-io.c 2003-09-02 22:00:43.000000000 +1200
@@ -781,6 +781,10 @@
/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back
* into life on wakeup from machine sleep.
*/
+#ifdef CONFIG_SOFTWARE_SUSPEND
+extern ide_startstop_t panic_box(ide_drive_t *drive);
+#endif
+
void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
{
ide_drive_t *drive;
@@ -835,6 +839,12 @@
/* no more work for this hwgroup (for now) */
return;
}
+#ifdef CONFIG_SOFTWARE_SUSPEND
+ if (hwgroup->handler == panic_box) {
+ printk("Trying to supress new request on blocked drive.\n");
+ return;
+ }
+#endif
hwif = HWIF(drive);
if (hwgroup->hwif->sharing_irq &&
hwif != hwgroup->hwif &&
diff -ruN swsusp-1.1-rc7/fs/buffer.c swsusp-1.1-rc8/fs/buffer.c
--- swsusp-1.1-rc7/fs/buffer.c 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/fs/buffer.c 2003-09-02 22:00:43.000000000 +1200
@@ -387,6 +387,11 @@
asmlinkage long sys_sync(void)
{
+ while (unlikely(swsusp_halt_io)) {
+ schedule();
+ if (unlikely(current->flags & PF_FREEZE))
+ refrigerator(PF_IOTHREAD);
+ }
fsync_dev(0);
return 0;
}
@@ -1207,14 +1212,10 @@
{
struct buffer_head * bh;
- if (unlikely(swsusp_trap_buffer_allocs)) {
- printnolog(SUSPEND_FREEZER, SUSPEND_HIGH, 0,
- "%s (%d) frozen at get_unused_buffer_head.\n");
- while (unlikely(swsusp_trap_buffer_allocs)) {
- if (current->flags & PF_FREEZE)
- refrigerator(PF_IOTHREAD);
- yield();
- }
+ while (unlikely(swsusp_halt_io)) {
+ if (current->flags & PF_FREEZE)
+ refrigerator(PF_IOTHREAD);
+ yield();
}
spin_lock(&unused_list_lock);
diff -ruN swsusp-1.1-rc7/include/linux/reboot.h swsusp-1.1-rc8/include/linux/reboot.h
--- swsusp-1.1-rc7/include/linux/reboot.h 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/include/linux/reboot.h 2003-09-02 22:00:43.000000000 +1200
@@ -52,8 +52,7 @@
* Architecture-independent suspend facility
*/
-extern void software_suspend_pending(void);
-extern unsigned char software_suspend_enabled;
+#include <linux/suspend.h>
#endif
diff -ruN swsusp-1.1-rc7/include/linux/suspend-common.h swsusp-1.1-rc8/include/linux/suspend-common.h
--- swsusp-1.1-rc7/include/linux/suspend-common.h 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/include/linux/suspend-common.h 2003-09-02 22:00:43.000000000 +1200
@@ -94,6 +94,7 @@
struct pagedir * pagedir;
int blocksperpage;
+ struct io_info * io_info;
} suspend_pbe_t;
typedef struct pagedir {
@@ -231,7 +232,7 @@
#define DEFAULT_SUSPEND_CONSOLE (MAX_NR_CONSOLES-1)
#endif
-#define TIMEOUT (3 * HZ) /* Timeout for stopping processes */
+#define TIMEOUT (6 * HZ) /* Timeout for stopping processes */
#define __ADDRESS(x) ((unsigned long) phys_to_virt(x))
#define ADDRESS(x) __ADDRESS((x) << PAGE_SHIFT)
@@ -356,7 +357,7 @@
extern kdev_t resume_device;
extern int resume_firstblock;
extern int resume_firstblocksize;
-int bdev_read_swap(struct pbe * pbe, int asyncio);
+int do_swsusp_io(int rw, struct pbe * pbe, int asyncio);
/* ------ ui.c ------ */
void check_shift_keys(int pause, char * message);
diff -ruN swsusp-1.1-rc7/include/linux/suspend-debug.h swsusp-1.1-rc8/include/linux/suspend-debug.h
--- swsusp-1.1-rc7/include/linux/suspend-debug.h 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/include/linux/suspend-debug.h 2003-09-02 22:00:43.000000000 +1200
@@ -6,7 +6,7 @@
#define name_suspend "Suspend Machine: "
#define name_resume "Resume Machine: "
-#define swsusp_version "1.1-rc7"
+#define swsusp_version "1.1-rc8"
#define name_swsusp "Swsusp " swsusp_version ": "
#define console_suspend " S U S P E N D T O D I S K " /* Same length to ensure one overwrites the other */
#define console_resume "R E S U M E F R O M D I S K"
diff -ruN swsusp-1.1-rc7/include/linux/suspend.h swsusp-1.1-rc8/include/linux/suspend.h
--- swsusp-1.1-rc7/include/linux/suspend.h 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/include/linux/suspend.h 2003-09-02 22:00:43.000000000 +1200
@@ -17,7 +17,7 @@
struct page * get_swsusp_pool_page(unsigned int gfp_mask, unsigned int order);
void free_swsusp_pool_pages(struct page *page, unsigned int order);
extern unsigned char swsusp_memory_pool_active;
-extern unsigned char swsusp_trap_buffer_allocs;
+extern unsigned char swsusp_halt_io;
#define SOFTWARE_SUSPEND_IDLE 0
#define SOFTWARE_SUSPEND_DISABLED 1
#define SOFTWARE_SUSPEND_RUNNING 2
diff -ruN swsusp-1.1-rc7/kernel/power/console.c swsusp-1.1-rc8/kernel/power/console.c
--- swsusp-1.1-rc7/kernel/power/console.c 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/kernel/power/console.c 2003-09-02 22:00:43.000000000 +1200
@@ -197,7 +197,7 @@
say_if_loglevel_changed();
if (printalways)
- printk("** %s\n", lastheader);
+ printk("\n** %s\n", lastheader);
if ((clearbar) && (SPLASH_IS_ON(suspend_console)))
fb_splash_set_progress(suspend_console, 0, 1, 1);
@@ -386,7 +386,7 @@
prepare_status(1, 1, "--- ESCAPE PRESSED : ABORTING PROCESS ---");
SET_RESULT_STATE(SUSPEND_ABORTED);
SET_RESULT_STATE(SUSPEND_ABORT_REQUESTED);
- abort_suspend("Alt key pressed.\n");
+ abort_suspend("Alt key pressed.");
}
#define SHIFT_AND_ALT (1 << KG_ALT | 1 << KG_SHIFT)
diff -ruN swsusp-1.1-rc7/kernel/power/io.c swsusp-1.1-rc8/kernel/power/io.c
--- swsusp-1.1-rc7/kernel/power/io.c 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/kernel/power/io.c 2003-09-02 22:00:43.000000000 +1200
@@ -15,7 +15,7 @@
extern void reset_io_stats(void);
extern void check_io_stats(void);
-extern int write_swap_page(struct pbe * pbe, int asyncio);
+extern int do_swsusp_io(int rw, struct pbe * pbe, int asyncio);
extern void swsusp_rw_swap_page(int rw, struct pbe * pbe);
extern unsigned long swapforimage;
extern unsigned long orig_mem_free;
@@ -258,7 +258,7 @@
struct page * origaddress = swap_pbe.address;
/* Submit previous buffer for writing */
swap_pbe.address = virt_to_page(compression_buffer);
- ret2 = write_swap_page(&swap_pbe, 1);
+ ret2 = do_swsusp_io(WRITE, &swap_pbe, 1);
if (ret2) {
zlib_deflateEnd(&strm);
abort_and_exit("Failed writing page to swap. Error number was %d.\n", ret);
@@ -297,7 +297,7 @@
if (!pbe.blocksperpage)
KDB_ENTER();
#endif
- ret = write_swap_page(&pbe, 1);
+ ret = do_swsusp_io(WRITE, &pbe, 1);
if (nr_free_pages() > origfree) {
printk("Nr free pages (%d) > origfree (%d).\n", nr_free_pages(), origfree);
check_shift_keys(1, NULL);
@@ -341,7 +341,7 @@
PRINTFREEMEM("at end of write pageset");
check_io_stats();
if (nr_free_pages() != origfree) {
- abort_suspend("Number of free pages at start and end of write pageset don't match! (%d != %d)\n", origfree, nr_free_pages());
+ abort_suspend("Number of free pages at start and end of write pageset don't match! (%d != %d)", origfree, nr_free_pages());
}
return result;
}
@@ -427,10 +427,16 @@
}
get_first_pbe(&swap_pbe, pagedir);
+
+ if (swap_pbe.blocksperpage != 1)
+ KDB_ENTER();
}
#endif
get_first_pbe(&pbe, pagedir);
+ if (pbe.blocksperpage != 1)
+ KDB_ENTER();
+
for (i=0; i< finish_at; i++) {
if (!(i&0x1FF))
printnolog(SUSPEND_IO, SUSPEND_LOW, 0, ".");
@@ -449,13 +455,15 @@
while ((strm.avail_out) && (ret != Z_STREAM_END) && (ret != Z_BUF_ERROR)) {
if (!strm.avail_in) {
+ int j;
/* Get next page of the compressed image */
readpbe.swap_address = swap_pbe.swap_address;
readpbe.swap_bdev = swap_pbe.swap_bdev;
- for (i = 0; i < swap_pbe.blocksperpage; i++)
- readpbe.block[i] = swap_pbe.block[i];
+ readpbe.blocksperpage = swap_pbe.blocksperpage;
+ for (j = 0; j < swap_pbe.blocksperpage; j++)
+ readpbe.block[j] = swap_pbe.block[j];
readpbe.address = virt_to_page(compression_buffer);
- ret2 = bdev_read_swap(&readpbe, 0);
+ ret2 = do_swsusp_io(READ, &readpbe, 0);
if (ret2)
abort_and_exit("Failed reading page to swap. Error number was %d.\n", ret);
strm.next_in = (char *) compression_buffer;
@@ -476,7 +484,7 @@
kunmap(pbe.address);
} else {
#endif
- if (bdev_read_swap(&pbe, 1)) {
+ if (do_swsusp_io(READ, &pbe, 1)) {
result = -EIO;
abort_and_exit("Failed to read page %lx from swap to %lx!", pbe.swap_address.val, dest_address);
}
@@ -487,6 +495,9 @@
check_shift_keys(0, NULL);
get_next_pbe(&pbe);
+
+ if (!pbe.blocksperpage)
+ KDB_ENTER();
}
update_status(1, 1, NULL);
@@ -532,7 +543,7 @@
headerpbe = (struct pbe *) __get_free_pages(GFP_ATOMIC, order);
if (!headerpbe) {
- abort_suspend("Unable to allocate page(s) for swap header pbes.\n");
+ abort_suspend("Unable to allocate page(s) for swap header pbes.");
return 1;
}
@@ -540,7 +551,7 @@
for (i=0; i<=num_range_pages; i++) {
headerpbe[i].swap_address = get_swap_page();
if (!headerpbe[i].swap_address.val) {
- abort_suspend("Unable to allocate swap page for header.\n");
+ abort_suspend("Unable to allocate swap page for header.");
return 1;
}
get_header_params(&headerpbe[i]);
@@ -630,7 +641,7 @@
diskpage.address = (unsigned long) rangepageslist[i];
diskpage.pointer->link.next = prev;
- ret = write_swap_page(&headerpbe[i], 1);
+ ret = do_swsusp_io(WRITE, &headerpbe[i], 1);
if (ret)
abort_and_exit("Failed writing page to swap. Error number was %d.\n", ret);
@@ -674,7 +685,7 @@
flush_dcache_page(virt_to_page(headerpbe[0].address));
diskpage.pointer->link.next = prev;
- write_swap_page(&headerpbe[0], 1);
+ do_swsusp_io(WRITE, &headerpbe[0], 1);
printlog(SUSPEND_IO, SUSPEND_VERBOSE, "S");
update_status(total - 1, total, NULL);
@@ -703,33 +714,19 @@
absolutise_ranges(rangepageslist);
- for (i = 0; i < MAX_SWAPFILES; i++)
+ for (i = 0; i < MAX_SWAPFILES; i++) {
absolutise_chain(&pagedir1.block_chain[i], rangepageslist);
-
- absolutise_chain(&pagedir1.origranges, rangepageslist);
- absolutise_chain(&pagedir1.destranges, rangepageslist);
- absolutise_chain(&pagedir1.swapranges, rangepageslist);
- absolutise_chain(&pagedir1.allocdranges, rangepageslist);
-
- put_rangepages_list(rangepageslist);
-
- if (!rangepageslist) {
- rangepageslist = get_rangepages_list();
-
- if (!rangepageslist) {
- panic("Unable to allocate rangepageslist.\n");
- }
+ print_chain(SUSPEND_HIGH, &pagedir1.block_chain[i], 0);
}
-
- absolutise_ranges(rangepageslist);
-
- for (i = 0; i < MAX_SWAPFILES; i++)
- absolutise_chain(&pagedir1.block_chain[i], rangepageslist);
absolutise_chain(&pagedir1.origranges, rangepageslist);
+ print_chain(SUSPEND_HIGH, &pagedir1.origranges, 0);
absolutise_chain(&pagedir1.destranges, rangepageslist);
+ print_chain(SUSPEND_HIGH, &pagedir1.destranges, 0);
absolutise_chain(&pagedir1.swapranges, rangepageslist);
+ print_chain(SUSPEND_HIGH, &pagedir1.swapranges, 0);
absolutise_chain(&pagedir1.allocdranges, rangepageslist);
+ print_chain(SUSPEND_HIGH, &pagedir1.allocdranges, 0);
put_rangepages_list(rangepageslist);
@@ -969,9 +966,9 @@
this_range_page = next_range_page;
}
if (!this_range_page)
- abort_suspend("Unable to allocate a pagedir.\n");
+ abort_suspend("Unable to allocate a pagedir.");
else
- abort_suspend("next.val NULL in __read_primary_suspend_image (range pages)!\n");
+ abort_suspend("next.val NULL in __read_primary_suspend_image (range pages)!");
//swsusp_spin_unlock_irq_restore(&suspend_pagedir_lock, swsuspirqflags);
return -ENOMEM;
}
diff -ruN swsusp-1.1-rc7/kernel/power/low_level_io.c swsusp-1.1-rc8/kernel/power/low_level_io.c
--- swsusp-1.1-rc7/kernel/power/low_level_io.c 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/kernel/power/low_level_io.c 2003-09-02 22:00:43.000000000 +1200
@@ -231,90 +231,93 @@
extern void end_buffer_io_sync(struct buffer_head * bh, int uptodate);
-void cleanup_write_swsusp_page_async(struct io_info * io_info)
+void cleanup_swsusp_page_io_async(struct io_info * io_info)
{
- struct buffer_head *bh = io_info->bh;
- struct page * page = bh->b_page;
-
- printlog(SUSPEND_IO, SUSPEND_MEDIUM, "Cleanup_write: [%p]\n", io_info);
- if (test_and_set_bit(IO_CLEANUP_IN_PROGRESS, &io_info->flags))
- return;
+ struct page * buffer_page;
+ struct page * data_page;
+ char *buffer_address, *data_address;
+ int reading;
+ pte_t * pte = NULL;
+ int pageprot = 0;
- TryLockPage(page); /* Ensure it's locked */
+ if ((unsigned long) io_info < __PAGE_OFFSET)
+ panic("Value of io_info (0x%p) passed to cleanup_swsusp_page_io is invalid!", io_info);
- if (!block_flushpage(page, 0))
- PAGE_BUG(page);
+ buffer_page = io_info->buffer_page;
- page->mapping = NULL;
- page->index = 0;
- UnlockPage(page);
-
- if (atomic_read(&page->count) != 2)
- printk(KERN_EMERG "Cleanup write: Page count is %d. Not good!\n", atomic_read(&page->count));
- atomic_dec(&page->count);
- __free_pages(page, 0);
-
- outstanding_io--;
- io_info->bh = NULL;
- io_info->flags = 0;
-}
-
-void cleanup_read_swsusp_page_async(struct io_info * io_info)
-{
- struct page *data_page = io_info->data_page, * buffer_page = io_info->buffer_page;
- struct buffer_head * bh = io_info->bh;
- pte_t * pte = NULL;
- int pageprot = 0;
- char * destaddress;
+ if ((unsigned long) buffer_page < __PAGE_OFFSET)
+ panic("Value of buffer_page (0x%p) passed to cleanup_swsusp_page_io is invalid!", buffer_page);
+ data_page = io_info->data_page;
+ if ((unsigned long) data_page < __PAGE_OFFSET)
+ panic("Value of data_page (0x%p) passed to cleanup_swsusp_page_io is invalid!", data_page);
+
if (test_and_set_bit(IO_CLEANUP_IN_PROGRESS, &io_info->flags))
return;
- printlog(SUSPEND_IO, SUSPEND_HIGH, "Cleanup_read: [%p:%p %p]", io_info, data_page, bh);
- clear_bit(IO_RESTORE_PAGE_PROT, &io_info->flags);
-
- // Remove any page protection while we restore contents
- if (test_bit(IO_HANDLE_PAGE_PROT, &io_info->flags)) {
- pte = lookup_address((unsigned long) page_address(data_page));
- printlog(SUSPEND_IO, SUSPEND_VERBOSE, "pte %p", pte);
- if (pte) {
- pageprot = pte->pte_low & ~_PAGE_CHG_MASK;
- if (pageprot != pgprot_val(PAGE_KERNEL_NOCACHE)) {
- set_pte(pte, pte_modify(*pte, PAGE_KERNEL_NOCACHE));
- set_bit(IO_RESTORE_PAGE_PROT, &io_info->flags);
- }
- }
- }
- io_info->pte = pte;
- io_info->pageprot = pageprot;
-
- destaddress=kmap(data_page);
- printlog(SUSPEND_IO, SUSPEND_VERBOSE, "destaddr: %p", destaddress);
- memcpy(destaddress, bh->b_data, PAGE_SIZE);
- flush_dcache_page(data_page);
- kunmap(data_page);
-
- if (test_bit(IO_RESTORE_PAGE_PROT, &io_info->flags))
- set_pte(io_info->pte, pte_modify(*(io_info->pte), __pgprot(io_info->pageprot)));
+ reading = test_bit(IO_AWAITING_READ, &io_info->flags);
+ printlog(SUSPEND_IO, SUSPEND_MEDIUM, "Cleanup IO: [%p]\n",
+ io_info);
TryLockPage(buffer_page); /* Ensure it's locked */
if (!block_flushpage(buffer_page, 0))
PAGE_BUG(buffer_page);
+ sync_page(buffer_page);
+
buffer_page->mapping = NULL;
buffer_page->index = 0;
UnlockPage(buffer_page);
+
+ if (reading) {
+ data_address = (char *) kmap(data_page);
+ if ((unsigned long) data_address < __PAGE_OFFSET)
+ panic("Value of data_address (0x%p) obtained in cleanup_swsusp_page_io is invalid!", data_address);
+
+ buffer_address = (char *) kmap(buffer_page);
+ if ((unsigned long) buffer_address < __PAGE_OFFSET)
+ panic("Value of buffer_address (0x%p) obtained in cleanup_swsusp_page_io is invalid!", buffer_address);
+
+ clear_bit(IO_RESTORE_PAGE_PROT, &io_info->flags);
+
+ // Remove any page protection while we restore contents
+ if (test_bit(IO_HANDLE_PAGE_PROT, &io_info->flags)) {
+ pte = lookup_address((unsigned long) data_address);
+ printlog(SUSPEND_IO, SUSPEND_VERBOSE, "pte %p", pte);
+ if (pte) {
+ pageprot = pte->pte_low & ~_PAGE_CHG_MASK;
+ if (pageprot != pgprot_val(PAGE_KERNEL_NOCACHE)) {
+ set_pte(pte, pte_modify(*pte, PAGE_KERNEL_NOCACHE));
+ set_bit(IO_RESTORE_PAGE_PROT, &io_info->flags);
+ }
+ }
+ }
+ io_info->pte = pte;
+ io_info->pageprot = pageprot;
+
+ memcpy(data_address, buffer_address, PAGE_SIZE);
+ flush_dcache_page(data_page);
+ kunmap(data_page);
+ kunmap(buffer_address);
+ if (test_bit(IO_RESTORE_PAGE_PROT, &io_info->flags))
+ set_pte(io_info->pte, pte_modify(*(io_info->pte), __pgprot(io_info->pageprot)));
+ }
+
+ if (atomic_read(&buffer_page->count) != 2)
+ printk(KERN_EMERG "Cleanup IO: Page count is %d. Not good!\n", atomic_read(&buffer_page->count));
atomic_dec(&buffer_page->count);
__free_pages(buffer_page, 0);
- free_suspend_cache_page(io_info->cache_page);
- io_info->cache_page = NULL;
+
+ if (reading) {
+ free_suspend_cache_page(io_info->cache_page);
+ io_info->cache_page = NULL;
+ }
+ outstanding_io--;
io_info->bh = NULL;
io_info->flags = 0;
- outstanding_io--;
- printlog(SUSPEND_IO, SUSPEND_HIGH, "\n");
}
int swsusp_brw_page(int rw, struct page *page, kdev_t dev, int b[], int size)
@@ -363,12 +366,8 @@
/* We clean up all we can at once so we don't only batch the first lot */
while (this) {
- if ((this->bh) && (this->bh->b_page) && (!buffer_locked(this->bh)) && (!PageLocked(this->bh->b_page))) {
- if (test_bit(IO_AWAITING_READ, &this->flags))
- cleanup_read_swsusp_page_async(this);
- else if (test_bit(IO_AWAITING_WRITE, &this->flags))
- cleanup_write_swsusp_page_async(this);
- }
+ if ((this->bh) && (this->bh->b_page) && (!buffer_locked(this->bh)) && (!PageLocked(this->bh->b_page)))
+ cleanup_swsusp_page_io_async(this);
if ((!test_bit(IO_IN_USE, &this->flags)) && (!firstfree))
firstfree = this;
this = this->next;
@@ -391,12 +390,8 @@
/* We clean up all we can at once so we don't only batch the first lot */
while (this) {
- if ((this->bh) && (this->bh->b_page) && (!buffer_locked(this->bh)) && (!PageLocked(this->bh->b_page))) {
- if (test_bit(IO_AWAITING_READ, &this->flags))
- cleanup_read_swsusp_page_async(this);
- else if (test_bit(IO_AWAITING_WRITE, &this->flags))
- cleanup_write_swsusp_page_async(this);
- }
+ if ((this->bh) && (this->bh->b_page) && (!buffer_locked(this->bh)) && (!PageLocked(this->bh->b_page)))
+ cleanup_swsusp_page_io_async(this);
if ((!test_bit(IO_IN_USE, &this->flags)) && (!firstfree))
firstfree = this;
last = this;
@@ -455,12 +450,8 @@
pageaddress = (unsigned long) this;
while (this) {
do { /* Forward at least one */
- if ((this->bh) && (this->bh->b_page) && (!buffer_locked(this->bh)) && (!PageLocked(this->bh->b_page))) {
- if (test_bit(IO_AWAITING_READ, &this->flags))
- cleanup_read_swsusp_page_async(this);
- else if (test_bit(IO_AWAITING_WRITE, &this->flags))
- cleanup_write_swsusp_page_async(this);
- }
+ if ((this->bh) && (this->bh->b_page) && (!buffer_locked(this->bh)) && (!PageLocked(this->bh->b_page)))
+ cleanup_swsusp_page_io_async(this);
if (test_bit(IO_IN_USE, &this->flags)) {
pageused = 1;
numleft++;
@@ -549,9 +540,11 @@
if (!io_info)
return 1;
- printlog(SUSPEND_IO, SUSPEND_MEDIUM, "Start_write: [%p]", io_info);
- while (!(buffer_virt = get_zeroed_page(GFP_ATOMIC)))
+ printlog(SUSPEND_IO, SUSPEND_MEDIUM, "Start_IO: [%p]", io_info);
+ while (!(buffer_virt = get_zeroed_page(GFP_ATOMIC))) {
+ run_task_queue(&tq_disk);
cleanup_finished_swsusp_io();
+ }
printlog(SUSPEND_IO, SUSPEND_HIGH, "[ALLOC BUFFER]->%d", nr_free_pages());
buffer_page = virt_to_page(buffer_virt);
@@ -582,12 +575,6 @@
for (i = 0; i < pbe->blocksperpage; i++)
io_info->zones[i] = pbe->block[i];
- for (i = 0; i < pbe->blocksperpage; i++)
- printnolog(SUSPEND_IO, SUSPEND_VERBOSE, 0,
- "%lx%s",
- pbe->block[i],
- ((i+1) < pbe->blocksperpage) ? "," : "");
-
io_info->zones_used = pbe->blocksperpage;
io_info->block_size = PAGE_SIZE / pbe->blocksperpage;
swsusp_brw_page(rw, buffer_page, io_info->dev, io_info->zones, io_info->block_size);
@@ -603,53 +590,11 @@
outstanding_io++;
if (outstanding_io > max_outstanding_io)
max_outstanding_io++;
+ pbe->io_info = io_info;
return 0;
}
-/*
- * swsusp_rw_swap_page:
- * Based on __rw_swap_page_nolock.
- * Asynchronously reads or writes a page to swap.
- * Used to read/write swap header.
- */
-int swsusp_rw_swap_page(int rw, struct pbe * pbe)
-{
- struct page * page = pbe->address, * cache_page;
- swp_entry_t entry = pbe->swap_address;
-
- atomic_inc(&page->count);
- lock_page(page);
- if (page->mapping)
- PAGE_BUG(page);
-
- /* needs sync_page to wait I/O completation */
- page->mapping = &swapper_space;
- last_suspend_cache_page = NULL;
-
- if (rw_swap_page_base(rw, entry, page))
- lock_page(page);
- else
- return 1; /* Invalid entry */
-
- if (!block_flushpage(page, 0))
- PAGE_BUG(page);
- page->mapping = NULL;
- UnlockPage(page);
-
- if (last_suspend_cache_page)
- cache_page = last_suspend_cache_page;
- else
- cache_page = 0;
-
- sync_page(page);
- if ((rw == READ) && (cache_page))
- free_suspend_cache_page(cache_page);
- atomic_dec(&page->count);
-
- return 0;
-}
-
void read_swapfiles(void) /* This is called before saving image */
{
int i, len;
@@ -694,6 +639,28 @@
sync_swap_partitions();
}
+int do_swsusp_io(int rw, struct pbe * pbe, int asyncio)
+{
+ int result = 0;
+ struct io_info * io_info = NULL;
+ result = start_swsusp_page_io_async(rw, pbe);
+ if (!result) {
+ if ((!asyncio) ||
+ ((rw == READ) && TEST_ACTION_STATE(SUSPEND_NO_ASYNC_READS)) ||
+ ((rw == WRITE) && TEST_ACTION_STATE(SUSPEND_NO_ASYNC_WRITES))) {
+ /* Since no other I/O is being submitted, we don't have
+ * to worry about the io_info struct being immediately
+ * reused. */
+ io_info = pbe->io_info;
+ while (test_bit(IO_IN_USE, &io_info->flags)) {
+ run_task_queue(&tq_disk);
+ cleanup_finished_swsusp_io();
+ }
+ }
+ }
+ return result;
+}
+
/*
* mark_swapfiles:
* Change the swapfile signature as appropriate.
@@ -708,13 +675,13 @@
PRINTFREEMEM("at start of mark_swapfiles");
if (root_swap == 0xFFFF) {
- printk("Unable to save suspend header - you haven't turned on the swap partition specified with the resume= option.\n");
+ abort_suspend("Unable to save suspend header - you haven't turned on the swap partition specified with the resume= option.");
return;
}
pageaddress = get_zeroed_page(GFP_ATOMIC);
if (!pageaddress) {
- abort_suspend("\nOut of memory trying to get page for swap header.\n");
+ abort_suspend("Out of memory trying to get page for swap header.");
return;
}
@@ -722,11 +689,19 @@
signature = ((union p_diskpage) pageaddress).pointer->swh.magic.magic;
pbe.swap_address = SWP_ENTRY(root_swap, 0);
- if (swsusp_rw_swap_page(READ, &pbe)) {
+ get_header_params(&pbe);
+
+ if (do_swsusp_io(READ, &pbe, 0)) {
free_pages(pageaddress, 0);
return;
}
+#if 0
+ free_pages(pageaddress, 0);
+ abort_suspend("Test abort.");
+ return;
+#endif
+
switch(mode) {
case MARK_SWAP_RESUME:
if (!memcmp("std",signature,3))
@@ -742,7 +717,7 @@
memcpy(signature,"SWAPSPACE2",10);
else if ((!memcmp("SWAP-SPACE",signature,10))
&&(!memcmp("SWAPSPACE2",signature,10))) {
- abort_suspend("\nSwapspace is altered (%.10s)\n", signature);
+ abort_suspend("Swapspace is altered (%.10s)", signature);
free_pages(pageaddress, 0);
return;
}
@@ -754,7 +729,7 @@
else if ((!memcmp("SWAPSPACE2",signature,10)))
memcpy(signature,"STD",3);
else {
- abort_suspend("\nSwapspace is not swapspace (%.10s)\n", signature);
+ abort_suspend("Swapspace is not swapspace (%.10s)", signature);
free_pages(pageaddress, 0);
return;
}
@@ -774,7 +749,7 @@
break;
}
flush_dcache_page(virt_to_page(pageaddress)) ;
- swsusp_rw_swap_page(WRITE, &pbe);
+ do_swsusp_io(WRITE, &pbe, 0);
PRINTFREEMEM("before freeing pbe page in mark_swapfiles");
free_pages(pageaddress, 0);
PRINTFREEMEM("after freeing pbe page in mark_swapfiles");
@@ -792,7 +767,7 @@
flush_dcache_page(page) ;
kunmap(page);
if (!buffer_uptodate(bh)) {
- abort_suspend("buffer_uptodate false in bdev_read_page!\n");
+ abort_suspend("buffer_uptodate false in bdev_read_page!");
brelse(bh);
BFREE(bh);
return -1;
@@ -802,105 +777,6 @@
return 0;
}
-static int rw_swap_page_sync(int rw, swp_entry_t swap_address, struct page * data_page)
-{
- struct io_info io_info;
- unsigned long buffer_address;
- struct page *buffer_page = NULL;
- void * pageaddress;
- pte_t * pte;
- int pageprot = 0;
- int restore = 0;
-
- buffer_address = get_zeroed_page(__GFP_FAST);
- if (!buffer_address) {
- abort_suspend("Out of memory in rw_swap_page_sync.\n");
- return 1;
- }
-
- buffer_page = virt_to_page(buffer_address);
-
- io_info.buffer_page = buffer_page;
-
- atomic_inc(&buffer_page->count);
- atomic_inc(&buffer_page->count);
- lock_page(buffer_page);
-
- BUG_ON(buffer_page->mapping);
- buffer_page->mapping = &swapper_space;
-
- if (rw == WRITE) {
- pageaddress = kmap(data_page);
- memcpy((char *) buffer_address, (char *) pageaddress, PAGE_SIZE);
- flush_dcache_page(data_page);
- kunmap(data_page);
- }
-
- if (rw_swap_page_base(rw, swap_address, buffer_page))
- lock_page(buffer_page);
-
- if (last_suspend_cache_page)
- io_info.cache_page = last_suspend_cache_page;
- else
- io_info.cache_page = 0;
- last_suspend_cache_page = NULL;
-
- if (rw == WRITE) {
- if (!block_flushpage(buffer_page, 0))
- PAGE_BUG(buffer_page);
- }
- sync_page(buffer_page);
-
- buffer_page->mapping = NULL;
- UnlockPage(buffer_page);
-
- if (rw == READ) {
- pageaddress = kmap(data_page);
-
- // Remove any page protection while we restore contents
- pte = lookup_address((unsigned long) pageaddress);
- if (pte) {
- pageprot = pte->pte_low & ~_PAGE_CHG_MASK;
- if (pageprot != pgprot_val(PAGE_KERNEL_NOCACHE)) {
- set_pte(pte, pte_modify(*pte, PAGE_KERNEL_NOCACHE));
- restore = 1;
- }
- }
-
- memcpy((char *) pageaddress, (char *) buffer_address, PAGE_SIZE);
- flush_dcache_page(data_page);
-
- if (restore)
- set_pte(pte, pte_modify(*(pte), __pgprot(pageprot)));
-
- kunmap(data_page);
- }
-
- if ((rw == READ) && (io_info.cache_page))
- free_suspend_cache_page(io_info.cache_page);
- atomic_dec(&buffer_page->count);
- atomic_dec(&buffer_page->count);
- free_pages(buffer_address, 0);
-
- return 0;
-}
-
-int bdev_read_swap(struct pbe * pbe, int asyncio)
-{
- if ((TEST_ACTION_STATE(SUSPEND_NO_ASYNC_READS)) || (!asyncio))
- return bdev_read_page(pbe->swap_bdev, pbe->block[0], pbe->address);
- else
- return start_swsusp_page_io_async(READ, pbe);
-}
-
-int write_swap_page(struct pbe * pbe, int asyncio)
-{
- if ((TEST_ACTION_STATE(SUSPEND_NO_ASYNC_WRITES)) || (!asyncio))
- return rw_swap_page_sync(WRITE, pbe->swap_address, pbe->address);
- else
- return start_swsusp_page_io_async(WRITE, pbe);
-}
-
int noresume_fix_signature(union p_diskpage cur)
{
/*
diff -ruN swsusp-1.1-rc7/kernel/power/main.c swsusp-1.1-rc8/kernel/power/main.c
--- swsusp-1.1-rc7/kernel/power/main.c 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/kernel/power/main.c 2003-09-02 22:00:43.000000000 +1200
@@ -79,7 +79,7 @@
unsigned long swapforimage = 0;
int orig_loglevel = 0;
int orig_show_page_allocs = 0;
-unsigned char swsusp_trap_buffer_allocs = 0;
+unsigned char swsusp_halt_io = 0;
static void ide_unsuspend(void);
static void ide_suspend(void);
@@ -157,6 +157,8 @@
{
#ifdef CONFIG_BLK_DEV_IDE
ide_disk_unsuspend(0);
+
+ swsusp_halt_io = 0;
#endif
}
@@ -167,6 +169,8 @@
spin_lock_irqsave(&io_request_lock, flags);
+ swsusp_halt_io = 1;
+
do_suspend_sync();
ide_disk_suspend();
@@ -208,6 +212,7 @@
if (flags & RESUME_PHASE1) {
#ifdef CONFIG_BLK_DEV_IDE
ide_disk_unsuspend(1);
+ swsusp_halt_io = 0;
#endif
#ifdef CONFIG_BLK_DEV_MD
md_autostart_arrays();
@@ -868,7 +873,7 @@
out:
PRINTFREEMEM("at 'out'");
- swsusp_trap_buffer_allocs = 0;
+ swsusp_halt_io = 0;
#ifdef CONFIG_SOFTWARE_SUSPEND_COMPRESSION
if (!TEST_ACTION_STATE(SUSPEND_NO_COMPRESSION))
@@ -927,6 +932,9 @@
thaw_processes();
+ if (notify_resume())
+ printk(KERN_EMERG "Failed to notify resume chain.\n");
+
MDELAY(1000);
printlog(SUSPEND_ANY_SECTION, SUSPEND_LOW, "Minimum free memory reloading image was %ld.\n", swsusp_min_free);
check_shift_keys(1, "About to restore original console. ");
@@ -936,9 +944,6 @@
#endif
PRINTFREEMEM("at end of do_software_suspend");
- if (notify_resume())
- printk(KERN_EMERG "Failed to notify resume chain.\n");
-
software_suspend_state = SOFTWARE_SUSPEND_IDLE;
#ifdef CONFIG_PREEMPT
PRINTPREEMPTCOUNT("Exiting with preempt count");
diff -ruN swsusp-1.1-rc7/kernel/power/memory_pool.c swsusp-1.1-rc8/kernel/power/memory_pool.c
--- swsusp-1.1-rc7/kernel/power/memory_pool.c 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/kernel/power/memory_pool.c 2003-09-02 22:00:43.000000000 +1200
@@ -30,35 +30,35 @@
{
int i = 0;
unsigned int sizesought = 100;
- unsigned long *last = memory_pool, *this = NULL;
+ unsigned long *this = NULL;
unsigned long flags;
- spin_lock_irqsave(&memory_pool_lock, flags);
-
/* Pool must not be active for this to work */
if (swsusp_memory_pool_active) {
printk(name_suspend "Error. Trying to fill the memory pool when it is active.\n");
return;
}
- sizesought = (REAL_MAX_ASYNC + 30);
+ spin_lock_irqsave(&memory_pool_lock, flags);
+
+ sizesought = (REAL_MAX_ASYNC + 100);
#ifdef CONFIG_SOFTWARE_SUSPEND_COMPRESSION
if (!TEST_ACTION_STATE(SUSPEND_NO_COMPRESSION))
- sizesought = ((REAL_MAX_ASYNC) * 2 + 30);
+ sizesought = ((REAL_MAX_ASYNC) * 2 + 100);
#endif
for (i = 0; i < sizesought; i++) {
this = (unsigned long *) get_zeroed_page(GFP_ATOMIC);
if (!this) {
printk(name_suspend "Error. Wanted %d pages wanted for swsusp memory pool, got %d.\n", sizesought, i);
+ spin_unlock_irqrestore(&memory_pool_lock, flags);
return;
}
printlog(SUSPEND_MEM_POOL, SUSPEND_HIGH, "Adding page %p to memory pool.\n", this);
- *this = (unsigned long) last;
- last = this;
+ *this = (unsigned long) memory_pool;
+ memory_pool = this;
swsusp_pool_level++;
}
- memory_pool = this;
printlog(SUSPEND_MEM_POOL, SUSPEND_MEDIUM, "Added %d pages to memory pool.\n", i);
spin_unlock_irqrestore(&memory_pool_lock, flags);
@@ -115,17 +115,17 @@
if ((!memory_pool) && (!(gfp_mask & __GFP_WAIT))) {
if (!printederror) {
printk("Swsusp memory pool: Unable to fulfil atomic allocation.\n");
- printederror = 1;
#ifdef CONFIG_KDB
//KDB_ENTER();
#endif
}
+ printederror++;
return NULL;
}
while(!memory_pool) {
cleanup_finished_swsusp_io();
- yield();
+ schedule();
}
swsusp_spin_lock_irqsave(&memory_pool_lock, flags);
diff -ruN swsusp-1.1-rc7/kernel/power/pagedir.c swsusp-1.1-rc8/kernel/power/pagedir.c
--- swsusp-1.1-rc7/kernel/power/pagedir.c 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/kernel/power/pagedir.c 2003-09-02 22:00:43.000000000 +1200
@@ -65,16 +65,18 @@
}
printnolog(SUSPEND_PAGESETS, SUSPEND_VERBOSE, 1,
- "origaddress: %ld. address: %ld. swap: %lx. bdev:%x. blocks:",
- currentorig,
- currentaddress,
+ "origaddress: %lx. address: %lx. swap: %lx. bdev:%x. blocks (%d):",
+ pbe->origaddress,
+ pbe->address,
pbe->swap_address.val,
- pbe->swap_bdev);
+ pbe->swap_bdev,
+ pbe->blocksperpage);
+
for (i = 0; i < pbe->blocksperpage; i++)
printnolog(SUSPEND_PAGESETS, SUSPEND_VERBOSE, 0,
- "%lx%s",
+ "0x%lx%s",
pbe->block[i],
- ((i+1) < pbe->blocksperpage) ? "," : "");
+ ((i+1) < pbe->blocksperpage) ? "," : "\n");
}
void get_next_pbe(struct pbe * pbe)
@@ -103,7 +105,7 @@
pbe->swap_bdev = swapdevs[chainnum];
printnolog(SUSPEND_IO, SUSPEND_VERBOSE, 0,
- "Swap device is %x.\n", pbe->swap_bdev);
+ "Swap device is changing to %x.\n", pbe->swap_bdev);
if (!blksize_size[MAJOR(pbe->swap_bdev)]) {
blksize = 1024;
@@ -112,6 +114,10 @@
printk(name_resume "%x: Blocksize not set?", pbe->swap_bdev);
blksize = PAGE_SIZE;
}
+ printk("Pagesize is %ld. Blksize is %d. Blocksperpage is %d.\n",
+ PAGE_SIZE,
+ blksize,
+ pbe->blocksperpage);
pbe->blocksperpage = PAGE_SIZE / blksize;
setup_pbe_variable(&thisblock, &pbe->currentblockrange, &pbe->pagedir->block_chain[chainnum]);
@@ -135,17 +141,20 @@
pbe->origaddress = mem_map + currentorig;
pbe->address = mem_map + currentaddress;
pbe->swap_address = range_val_to_swap_entry(currentswap);
+
printnolog(SUSPEND_PAGESETS, SUSPEND_VERBOSE, 1,
- "origaddress: %ld. address: %ld. swap: %lx. bdev:%x. blocks:",
- currentorig,
- currentaddress,
+ "origaddress: %lx. address: %lx. swap: %lx. bdev:%x. blocks (%d):",
+ pbe->origaddress,
+ pbe->address,
pbe->swap_address.val,
- pbe->swap_bdev);
+ pbe->swap_bdev,
+ pbe->blocksperpage);
+
for (i = 0; i < pbe->blocksperpage; i++)
printnolog(SUSPEND_PAGESETS, SUSPEND_VERBOSE, 0,
- "%lx%s",
+ "0x%lx%s",
pbe->block[i],
- ((i+1) < pbe->blocksperpage) ? "," : "");
+ ((i+1) < pbe->blocksperpage) ? "," : "\n");
}
static void clear_map(unsigned long * pagemap)
@@ -165,7 +174,7 @@
} else {
check = (void *) __get_free_pages(__GFP_FAST, BITMAP_ORDER);
if (!check) {
- abort_suspend("Error. Unable to allocate memory for pagemap.\n");
+ abort_suspend("Error. Unable to allocate memory for pagemap.");
return 1;
}
if (setnosave)
@@ -292,7 +301,7 @@
}
if (max_mapnr != num_physpages) {
- abort_suspend("mapnr is not expected");
+ abort_suspend("Max_mapnr is not equal to num_physpages.");
result.size1 = -1;
result.size2 = -1;
result.size2low = -1;
@@ -318,7 +327,7 @@
}
} else {
if (PageNosave(mem_map+loop)) {
- abort_suspend("Reserved page marked nosave! (%lx)\n", ADDRESS(loop));
+ abort_suspend("Reserved page marked nosave! (%lx)", ADDRESS(loop));
result.size1 = 0;
result.size2 = 0;
result.size2low = 0;
diff -ruN swsusp-1.1-rc7/kernel/power/process.c swsusp-1.1-rc8/kernel/power/process.c
--- swsusp-1.1-rc7/kernel/power/process.c 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/kernel/power/process.c 2003-09-02 22:00:43.000000000 +1200
@@ -49,11 +49,12 @@
((p->flags & PF_IOTHREAD) || \
(p == current) || \
(p->state == TASK_ZOMBIE) || \
- (p->flags & PF_FROZEN) || \
+ (p->state == TASK_STOPPED) || \
(!strcmp(p->comm, "dosexec")) || \
(p->state == TASK_UNINTERRUPTIBLE))
/* (!(p->flags & PF_REFRIGERATE)) || \ */
+/* (p->flags & PF_FROZEN) || \ not necessary since testing for stopped now */
/* Processes which need to be frozen before others in this particular order */
static char * freeze_order[] = { "bdflush", "kupdated", "kjournald", "kswapd" };
@@ -112,13 +113,13 @@
*/
static int freeze_processes(void)
{
- int todo = 0, threadcount;
+ int todo = 0, threadcount, newtodo;
unsigned long start_time, iorequestflags;
struct task_struct *p;
int index = 0, origfrozen = processesfrozen;
freezing = 1;
- swsusp_trap_buffer_allocs = 1;
+ swsusp_halt_io = 1;
do_suspend_sync();
for_each_task(p) {
@@ -135,6 +136,7 @@
do {
int numsignalled = 0;
+ newtodo = 0;
threadcount = 0;
read_lock(&tasklist_lock);
for_each_task(p) {
@@ -173,7 +175,16 @@
}
}
yield();
- if ((time_after(jiffies, start_time + TIMEOUT)) && (todo > (processesfrozen - origfrozen))) {
+ printnolog(SUSPEND_FREEZER, SUSPEND_VERBOSE, 0, "Still to do:");
+ for_each_task(p) {
+ if (IS_IGNORED(p))
+ continue;
+ newtodo++;
+ printnolog(SUSPEND_FREEZER, SUSPEND_VERBOSE, 0, "%s (%d); ",
+ p->comm, p->pid);
+ }
+ printnolog(SUSPEND_FREEZER, SUSPEND_VERBOSE, 0, "\n");
+ if ((time_after(jiffies, start_time + TIMEOUT)) && (newtodo)) {
printk(KERN_ERR name_suspend "Stopping tasks failed.\n");
printk(KERN_ERR "Tasks that refused to be refrigerated and haven't since exited:\n");
read_lock(&tasklist_lock);
@@ -193,21 +204,22 @@
p->comm, p->pid);
}
read_lock(&tasklist_lock);
+ show_state();
freezing = 0;
- do_suspend_sync();
- swsusp_trap_buffer_allocs = 0;
+ swsusp_halt_io = 0;
swsusp_spin_unlock_irqrestore(&io_request_lock, iorequestflags);
+ do_suspend_sync();
return todo - (processesfrozen - origfrozen);
}
if (processestofreeze)
- update_status(todo - (processesfrozen - origfrozen), todo,
- "%d/%d", todo - (processesfrozen - origfrozen), todo);
- } while(todo > (processesfrozen - origfrozen));
+ update_status(todo - newtodo, todo,
+ "%d/%d", todo - newtodo, todo);
+ } while(newtodo);
suspend_task = current->pid;
freezing = 0;
do_suspend_sync();
- swsusp_trap_buffer_allocs = 0;
+ swsusp_halt_io = 0;
swsusp_spin_unlock_irqrestore(&io_request_lock, iorequestflags);
@@ -218,21 +230,27 @@
void thaw_processes(void)
{
- struct task_struct *p;
+ struct task_struct *p, *last = NULL;
printnolog(SUSPEND_FREEZER, SUSPEND_LOW, 1, name_resume "Thawing tasks\n");
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if (p->flags & PF_FROZEN) {
+ suspend_task = 0;
+
+ do {
+ last = NULL;
+ read_lock(&tasklist_lock);
+ for_each_task(p)
+ if (p->flags & PF_FROZEN) {
+ last = p;
+ break;
+ }
+ read_unlock(&tasklist_lock);
+ if (last) {
printnolog(SUSPEND_FREEZER, SUSPEND_VERBOSE, 0, "Waking %5d: %s.\n", p->pid, p->comm);
- p->flags &= ~PF_FROZEN;
- wake_up_process(p);
+ //printk("Waking %5d: %s.\n", last->pid, last->comm);
+ last->flags &= ~PF_FROZEN;
+ wake_up_process(last);
}
- }
- read_unlock(&tasklist_lock);
- yield();
-
- suspend_task = 0;
+ } while (last);
}
/*
@@ -372,15 +390,16 @@
return 0;
}
+#define MAX_ATTEMPTS 1
+
int attempt_to_freeze(void)
{
- int lastfreezeresult, freezeattemptsleft = 3;
+ int lastfreezeresult, freezeattemptsleft = MAX_ATTEMPTS;
/* Stop processes before checking again */
do {
thaw_processes();
- yield();
- prepare_status(1, 1, "Freezing processes: Attempt %d", 4 - freezeattemptsleft);
+ prepare_status(1, 1, "Freezing processes: Attempt %d", MAX_ATTEMPTS + 1 - freezeattemptsleft);
lastfreezeresult = freeze_processes();
freezeattemptsleft--;
//printk(KERN_ERR "Last freeze result was %d.\n", lastfreezeresult);
@@ -388,7 +407,7 @@
//printk("Exiting attempt to freeze with result %d.\n", lastfreezeresult);
if (lastfreezeresult) {
- show_state();
+ //show_state();
SET_RESULT_STATE(SUSPEND_ABORTED);
SET_RESULT_STATE(SUSPEND_FREEZING_FAILED);
}
diff -ruN swsusp-1.1-rc7/kernel/power/range.c swsusp-1.1-rc8/kernel/power/range.c
--- swsusp-1.1-rc7/kernel/power/range.c 2003-09-02 22:00:41.000000000 +1200
+++ swsusp-1.1-rc8/kernel/power/range.c 2003-09-02 22:00:43.000000000 +1200
@@ -203,7 +203,7 @@
void print_chain(int debuglevel, struct rangechain * chain, int printashex)
{
-#if 0
+#if 1
struct range * this = chain->first;
int count = 0, size = 0;