diff options
author | Pavel Machek <pavel@ucw.cz> | 2004-06-17 18:08:43 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-06-17 18:08:43 -0700 |
commit | af5bb145f0399c6a60a651a74ec3a7d2a58be125 (patch) | |
tree | 189bcca6c8544d1a70a5e6f52f5927b80b21e65e /kernel | |
parent | 48813c1e8212b518f1b65466fc0911d5d0f996e2 (diff) | |
download | history-af5bb145f0399c6a60a651a74ec3a7d2a58be125.tar.gz |
[PATCH] Fix memory leak in swsusp
This fixes 2 memory leaks in swsusp: during relocating pagedir, eaten pages
were not properly freed in error path and even regular freeing path was
freeing one page too little.
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/power/swsusp.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 752f6cdb438296..886a6d9b38c26b 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -503,6 +503,9 @@ static int count_and_copy_zone(struct zone *zone, struct pbe **pagedir_p) if (!pbe) continue; pbe->orig_address = (long) page_address(page); + /* Copy page is dangerous: it likes to mess with + preempt count on specific cpus. Wrong preempt count is then copied, + oops. */ copy_page((void *)pbe->address, (void *)pbe->orig_address); pbe++; } @@ -923,8 +926,9 @@ static int relocate_pagedir(void) suspend_pagedir_t *new_pagedir, *old_pagedir = pagedir_nosave; void **eaten_memory = NULL; void **c = eaten_memory, *m, *f; + int ret = 0; - printk("Relocating pagedir"); + printk("Relocating pagedir "); if(!does_collide_order(old_pagedir, (unsigned long)old_pagedir, pagedir_order)) { printk("not necessary\n"); @@ -941,22 +945,23 @@ static int relocate_pagedir(void) c = eaten_memory; } - if (!m) - return -ENOMEM; - - pagedir_nosave = new_pagedir = m; - copy_pagedir(new_pagedir, old_pagedir); + if (!m) { + printk("out of memory\n"); + ret = -ENOMEM; + } else { + pagedir_nosave = new_pagedir = m; + copy_pagedir(new_pagedir, old_pagedir); + } c = eaten_memory; - while(c) { + while (c) { printk(":"); - f = *c; + f = c; c = *c; - if (f) - free_pages((unsigned long)f, pagedir_order); + free_pages((unsigned long)f, pagedir_order); } printk("|\n"); - return 0; + return ret; } /* |