From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Pavel Machek <pavel@suse.cz>
Cc: LKML <linux-kernel@vger.kernel.org>, linux-pm@osdl.org
Subject: [RFC][PATCH 6/6] swsusp: improve freeing of memory
Date: Sat, 29 Oct 2005 22:46:50 +0200 [thread overview]
Message-ID: <200510292246.50685.rjw@sisk.pl> (raw)
In-Reply-To: <200510292158.11089.rjw@sisk.pl>
This is the bonus patch not functionally related to the previous patches
that speeds up swsusp substantially (on my box swsusp is two times
faster with it) and makes the system be much more responsive after
resume.
However, it only makes sense if the limit imposed by the size of the
swsusp_info structure is lifted, which is done in one of the previous
patches.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
include/linux/suspend.h | 2 -
kernel/power/disk.c | 30 ++----------------------
kernel/power/power.h | 1
kernel/power/snapshot.c | 6 +---
kernel/power/swsusp.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 67 insertions(+), 32 deletions(-)
Index: linux-2.6.14-rc5-mm1/kernel/power/disk.c
===================================================================
--- linux-2.6.14-rc5-mm1.orig/kernel/power/disk.c 2005-10-29 14:01:27.000000000 +0200
+++ linux-2.6.14-rc5-mm1/kernel/power/disk.c 2005-10-29 14:12:12.000000000 +0200
@@ -24,6 +24,7 @@
extern suspend_disk_method_t pm_disk_mode;
+extern int swsusp_shrink_memory(void);
extern int swsusp_suspend(void);
extern int swsusp_write(void);
extern int swsusp_check(void);
@@ -73,31 +74,6 @@
static int in_suspend __nosavedata = 0;
-/**
- * free_some_memory - Try to free as much memory as possible
- *
- * ... but do not OOM-kill anyone
- *
- * Notice: all userland should be stopped at this point, or
- * livelock is possible.
- */
-
-static void free_some_memory(void)
-{
- 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++ % 4]);
- }
- printk("\bdone (%li pages freed)\n", pages);
-}
-
-
static inline void platform_finish(void)
{
if (pm_disk_mode == PM_DISK_PLATFORM) {
@@ -127,8 +103,8 @@
}
/* Free memory before shutting down devices. */
- free_some_memory();
- return 0;
+ if (!(error = swsusp_shrink_memory()))
+ return 0;
thaw:
thaw_processes();
enable_nonboot_cpus();
Index: linux-2.6.14-rc5-mm1/kernel/power/power.h
===================================================================
--- linux-2.6.14-rc5-mm1.orig/kernel/power/power.h 2005-10-29 14:12:07.000000000 +0200
+++ linux-2.6.14-rc5-mm1/kernel/power/power.h 2005-10-29 14:12:12.000000000 +0200
@@ -58,6 +58,7 @@
extern asmlinkage int swsusp_arch_suspend(void);
extern asmlinkage int swsusp_arch_resume(void);
+extern unsigned count_data_pages(void);
extern void swsusp_free(void);
extern unsigned snapshot_pages_to_save(void);
Index: linux-2.6.14-rc5-mm1/kernel/power/snapshot.c
===================================================================
--- linux-2.6.14-rc5-mm1.orig/kernel/power/snapshot.c 2005-10-29 14:12:07.000000000 +0200
+++ linux-2.6.14-rc5-mm1/kernel/power/snapshot.c 2005-10-29 14:12:12.000000000 +0200
@@ -67,17 +67,15 @@
BUG_ON(PageReserved(page) && PageNosave(page));
if (PageNosave(page))
return 0;
- if (PageReserved(page) && pfn_is_nosave(pfn)) {
- pr_debug("[nosave pfn 0x%lx]", pfn);
+ if (PageReserved(page) && pfn_is_nosave(pfn))
return 0;
- }
if (PageNosaveFree(page))
return 0;
return 1;
}
-static unsigned count_data_pages(void)
+unsigned count_data_pages(void)
{
struct zone *zone;
unsigned long zone_pfn;
Index: linux-2.6.14-rc5-mm1/kernel/power/swsusp.c
===================================================================
--- linux-2.6.14-rc5-mm1.orig/kernel/power/swsusp.c 2005-10-29 14:12:07.000000000 +0200
+++ linux-2.6.14-rc5-mm1/kernel/power/swsusp.c 2005-10-29 14:12:12.000000000 +0200
@@ -77,6 +77,30 @@
#include "power.h"
#ifdef CONFIG_HIGHMEM
+static unsigned count_highmem_pages(void)
+{
+ struct zone *zone;
+ unsigned n = 0;
+
+ for_each_zone (zone)
+ if (is_highmem(zone)) {
+ mark_free_pages(zone);
+ 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 (PageReserved(page))
+ continue;
+ if (PageNosaveFree(page))
+ continue;
+ n++;
+ }
+ }
+ return n;
+}
+
struct highmem_page {
char *data;
struct page *page;
@@ -163,10 +187,46 @@
return 0;
}
#else
+static unsigned count_highmem_pages(void) { return 0; }
static int save_highmem(void) { return 0; }
static int restore_highmem(void) { return 0; }
#endif /* CONFIG_HIGHMEM */
+/**
+ * swsusp_shrink_memory - Try to free as much memory as needed
+ *
+ * ... but do not OOM-kill anyone
+ *
+ * Notice: all userland should be stopped before it is called, or
+ * livelock is possible.
+ */
+
+int swsusp_shrink_memory(void)
+{
+ unsigned long cnt;
+ long tmp;
+ unsigned long pages = 0;
+ unsigned int i = 0;
+ char *p = "-\\|/";
+
+ printk("Shrinking memory... ");
+ do {
+ cnt = count_data_pages() + count_highmem_pages();
+ cnt += (cnt + PBES_PER_PAGE - 1) / PBES_PER_PAGE +
+ PAGES_FOR_IO;
+ tmp = cnt - nr_free_pages();
+ if (tmp > 0) {
+ tmp = 10000;
+ cnt = shrink_all_memory(tmp);
+ pages += cnt;
+ }
+ printk("\b%c", p[i++%4]);
+ } while (tmp > 0 && cnt > 0);
+ printk("\bdone (%lu pages freed)\n", pages);
+
+ return tmp > 0 ? -ENOMEM : 0;
+}
+
int swsusp_suspend(void)
{
int error;
Index: linux-2.6.14-rc5-mm1/include/linux/suspend.h
===================================================================
--- linux-2.6.14-rc5-mm1.orig/include/linux/suspend.h 2005-10-29 14:01:27.000000000 +0200
+++ linux-2.6.14-rc5-mm1/include/linux/suspend.h 2005-10-29 14:42:16.000000000 +0200
@@ -73,6 +73,6 @@
* XXX: We try to keep some more pages free so that I/O operations succeed
* without paging. Might this be more?
*/
-#define PAGES_FOR_IO 512
+#define PAGES_FOR_IO 1024
#endif /* _LINUX_SWSUSP_H */
next prev parent reply other threads:[~2005-10-29 20:46 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-10-29 19:58 [RFC][PATCH 0/6] swsusp: rework swap handling Rafael J. Wysocki
2005-10-29 20:01 ` [RFC][PATCH 1/6] swsusp: rework swsusp_suspend Rafael J. Wysocki
2005-10-29 22:25 ` Pavel Machek
2005-10-29 20:06 ` [RFC][PATCH 2/6] swsusp: move snapshot-handling functions to snapshot.c Rafael J. Wysocki
2005-10-29 22:27 ` Pavel Machek
2005-10-29 20:32 ` [RFC][PATCH 3/6] swsusp: introduce the swap map structure and interface functions Rafael J. Wysocki
2005-10-29 22:57 ` Pavel Machek
2005-10-29 23:20 ` Pavel Machek
2005-10-29 20:36 ` [RFC][PATCH 4/6] swsusp: move swap check out of swsusp_suspend Rafael J. Wysocki
2005-10-29 23:21 ` Pavel Machek
2005-10-30 12:40 ` Rafael J. Wysocki
2005-10-30 11:46 ` Pavel Machek
2005-10-29 20:41 ` [RFC][PATCH 5/6] swsusp: move swap-handling functions to separate file Rafael J. Wysocki
2005-10-30 13:33 ` Pavel Machek
2005-10-29 20:46 ` Rafael J. Wysocki [this message]
2005-10-29 23:05 ` [RFC][PATCH 0/6] swsusp: rework swap handling Pavel Machek
2005-10-30 12:17 ` Pavel Machek
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=200510292246.50685.rjw@sisk.pl \
--to=rjw@sisk.pl \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@osdl.org \
--cc=pavel@suse.cz \
/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