From: Pavel Machek <pavel@ucw.cz>
To: Andrew Morton <akpm@osdl.org>
Cc: linux-kernel@vger.kernel.org
Subject: Re: swsusp update: supports discontingmem/highmem
Date: Tue, 6 Apr 2004 14:15:22 +0200 [thread overview]
Message-ID: <20040406121522.GH3693@elf.ucw.cz> (raw)
In-Reply-To: <20040405153507.69e3004d.akpm@osdl.org>
Hi!
> > It makes swsusp behave correctly
> > w.r.t. discontingmem, and adds highmem handling
>
> Some of those ENOMEM panics in save_highmem_zone() look like they might
> need proper handling instead?
Done.
> The 256 byte automatic array in read_swapfiles() may bring you a visit from
> the stack space police, although I don't think it's really a problem. 256
> bytes for a pathname may be a bit excessive though.
Marked static, its only called once anyway.
> Please send me an update patch sometime which makes all the new code go
> away again if !CONFIG_HIGHMEM.
Done; plus I added some warnings to swsusp.S (based on discussion with
wli). Relative to previous diff, please apply.
Pavel
--- tmp/linux/arch/i386/power/swsusp.S 2003-09-28 22:05:30.000000000 +0200
+++ linux/arch/i386/power/swsusp.S 2004-04-06 13:25:42.000000000 +0200
@@ -1,6 +1,13 @@
.text
-/* Originally gcc generated, modified by hand */
+/* Originally gcc generated, modified by hand
+ *
+ * This may not use any stack, nor any variable that is not "NoSave":
+ *
+ * Its rewriting one kernel image with another. What is stack in "old"
+ * image could very well be data page in "new" image, and overwriting
+ * your own stack under you is bad idea.
+ */
#include <linux/linkage.h>
#include <asm/segment.h>
--- tmp/linux/kernel/power/swsusp.c 2004-04-06 13:26:39.000000000 +0200
+++ linux/kernel/power/swsusp.c 2004-04-06 13:07:46.000000000 +0200
@@ -225,7 +225,7 @@
static void read_swapfiles(void) /* This is called before saving image */
{
int i, len;
- char buff[sizeof(resume_file)], *sname;
+ static char buff[sizeof(resume_file)], *sname;
len=strlen(resume_file);
root_swap = 0xFFFF;
@@ -366,6 +366,7 @@
return 0;
}
+#ifdef CONFIG_HIGHMEM
struct highmem_page {
char *data;
struct page *page;
@@ -374,7 +375,7 @@
struct highmem_page *highmem_copy = NULL;
-static void save_highmem_zone(struct zone *zone)
+static int save_highmem_zone(struct zone *zone)
{
unsigned long zone_pfn;
for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
@@ -384,7 +385,7 @@
unsigned long pfn = zone_pfn + zone->zone_start_pfn;
int chunk_size;
- if (!(pfn%200))
+ if (!(pfn%1000))
printk(".");
if (!pfn_valid(pfn))
continue;
@@ -397,7 +398,7 @@
*/
if (PageReserved(page)) {
printk("highmem reserved page?!\n");
- BUG();
+ continue;
}
if ((chunk_size = is_head_of_free_region(page))) {
pfn += chunk_size - 1;
@@ -406,26 +407,33 @@
}
save = kmalloc(sizeof(struct highmem_page), GFP_ATOMIC);
if (!save)
- panic("Not enough memory");
+ return -ENOMEM;
save->next = highmem_copy;
save->page = page;
save->data = (void *) get_zeroed_page(GFP_ATOMIC);
- if (!save->data)
- panic("Not enough memory");
+ if (!save->data) {
+ kfree(save);
+ return -ENOMEM;
+ }
kaddr = kmap_atomic(page, KM_USER0);
memcpy(save->data, kaddr, PAGE_SIZE);
kunmap_atomic(kaddr, KM_USER0);
highmem_copy = save;
}
+ return 0;
}
-static void save_highmem(void)
+static int save_highmem(void)
{
struct zone *zone;
+ int res = 0;
for_each_zone(zone) {
if (is_highmem(zone))
- save_highmem_zone(zone);
+ res = save_highmem_zone(zone);
+ if (res)
+ return res;
}
+ return 0;
}
static int restore_highmem(void)
@@ -443,6 +451,7 @@
}
return 0;
}
+#endif
static int pfn_is_nosave(unsigned long pfn)
{
@@ -460,7 +469,7 @@
struct page *page;
unsigned long pfn = zone_pfn + zone->zone_start_pfn;
- if (!(pfn%200))
+ if (!(pfn%1000))
printk(".");
if (!pfn_valid(pfn))
continue;
@@ -548,7 +557,7 @@
while(nr_copy_pages--) {
p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
- if(!p->address) {
+ if (!p->address) {
free_suspend_pagedir((unsigned long) pagedir);
return NULL;
}
@@ -589,10 +598,17 @@
unsigned int nr_needed_pages = 0;
pagedir_nosave = NULL;
- printk( "/critical section: Handling highmem" );
- save_highmem();
+ printk( "/critical section: ");
+#ifdef CONFIG_HIGHMEM
+ printk( "handling highmem" );
+ if (save_highmem()) {
+ printk(KERN_CRIT "%sNot enough free pages for highmem\n", name_suspend);
+ return -ENOMEM;
+ }
+ printk(", ");
+#endif
- printk(", counting pages to copy" );
+ printk("counting pages to copy" );
drain_local_pages();
nr_copy_pages = count_and_copy_data_pages(NULL);
nr_needed_pages = nr_copy_pages + PAGES_FOR_IO;
@@ -602,23 +618,22 @@
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 1;
+ 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 1;
+ return -ENOSPC;
}
PRINTK( "Alloc pagedir\n" );
pagedir_save = pagedir_nosave = create_suspend_pagedir(nr_copy_pages);
- if(!pagedir_nosave) {
- /* Shouldn't happen */
- printk(KERN_CRIT "%sCouldn't allocate enough pages\n",name_suspend);
- panic("Really should not happen");
- return 1;
+ 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;
@@ -702,8 +717,10 @@
PRINTK( "Freeing prev allocated pagedir\n" );
free_suspend_pagedir((unsigned long) pagedir_save);
+#ifdef CONFIG_HIGHMEM
printk( "Restoring highmem\n" );
restore_highmem();
+#endif
printk("done, devices\n");
device_power_up();
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]
prev parent reply other threads:[~2004-04-06 12:16 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-04-05 21:23 Pavel Machek
2004-04-05 22:24 ` Nigel Cunningham
2004-04-06 11:03 ` Pavel Machek
2004-04-05 22:35 ` Andrew Morton
2004-04-06 12:15 ` Pavel Machek [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040406121522.GH3693@elf.ucw.cz \
--to=pavel@ucw.cz \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®