From: Nick Piggin <nickpiggin@yahoo.com.au>
To: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Christoph Lameter <clameter@engr.sgi.com>,
Pavel Machek <pavel@ucw.cz>,
linux-mm@kvack.org
Subject: Re: Remove page flags for software suspend
Date: Fri, 02 Mar 2007 02:18:29 +1100 [thread overview]
Message-ID: <45E6EEC5.4060902@yahoo.com.au> (raw)
In-Reply-To: <200702281813.04643.rjw@sisk.pl>
[-- Attachment #1: Type: text/plain, Size: 1195 bytes --]
Rafael J. Wysocki wrote:
> On Wednesday, 28 February 2007 16:25, Christoph Lameter wrote:
>
>>On Wed, 28 Feb 2007, Pavel Machek wrote:
>>
>>
>>>I... actually do not like that patch. It adds code... at little or no
>>>benefit.
>>
>>We are looking into saving page flags since we are running out. The two
>>page flags used by software suspend are rarely needed and should be taken
>>out of the flags. If you can do it a different way then please do.
>
>
> As I have already said for a couple of times, I think we can and I'm going to
> do it, but right now I'm a bit busy with other things that I consider as more
> urgent.
I need one bit for lockless pagecache ;)
Anyway, I guess if you want something done you have to do it yourself.
This patch still needs work (and I don't know if it even works, because
I can't make swsusp resume even on a vanilla kernel). But this is my
WIP for removing swsusp page flags.
This patch adds a simple extent based nosave region tracker, and
rearranges some of the snapshot code to be a bit simpler and more
amenable to having dynamically allocated flags (they aren't actually
dynamically allocated in this patch, however).
--
SUSE Labs, Novell Inc.
[-- Attachment #2: swsusp-Nosave-use-extents.patch --]
[-- Type: text/plain, Size: 23907 bytes --]
---
arch/x86_64/kernel/e820.c | 8 --
include/linux/page-flags.h | 33 ++++----
include/linux/suspend.h | 12 ++-
kernel/power/Makefile | 2
kernel/power/main.c | 4 +
kernel/power/nosave.c | 103 +++++++++++++++++++++++++++
kernel/power/power.h | 1
kernel/power/snapshot.c | 167 ++++++++++++++++++++++-----------------------
mm/page_alloc.c | 34 ---------
9 files changed, 222 insertions(+), 142 deletions(-)
Index: linux-2.6/include/linux/suspend.h
===================================================================
--- linux-2.6.orig/include/linux/suspend.h 2007-03-02 01:51:08.000000000 +1100
+++ linux-2.6/include/linux/suspend.h 2007-03-02 02:06:07.000000000 +1100
@@ -21,7 +21,6 @@ struct pbe {
/* mm/page_alloc.c */
extern void drain_local_pages(void);
-extern void mark_free_pages(struct zone *zone);
#ifdef CONFIG_PM
/* kernel/power/swsusp.c */
@@ -42,6 +41,17 @@ static inline int software_suspend(void)
}
#endif /* CONFIG_PM */
+#ifdef CONFIG_SOFTWARE_SUSPEND
+/* kernel/power/nosave.c */
+extern int __init register_nosave_region(unsigned long start_pfn, unsigned long end_pfn);
+#else
+static inline int register_nosave_region(unsigned long start_pfn, unsigned long end_pfn)
+{
+ return 0;
+}
+#endif
+
+
void save_processor_state(void);
void restore_processor_state(void);
struct saved_context;
Index: linux-2.6/kernel/power/Makefile
===================================================================
--- linux-2.6.orig/kernel/power/Makefile 2007-03-02 01:51:08.000000000 +1100
+++ linux-2.6/kernel/power/Makefile 2007-03-02 02:06:07.000000000 +1100
@@ -5,6 +5,6 @@ endif
obj-y := main.o process.o console.o
obj-$(CONFIG_PM_LEGACY) += pm.o
-obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o snapshot.o swap.o user.o
+obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o snapshot.o swap.o user.o nosave.o
obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
Index: linux-2.6/kernel/power/nosave.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/kernel/power/nosave.c 2007-03-02 02:06:07.000000000 +1100
@@ -0,0 +1,103 @@
+/*
+ * Provide a way of tracking a set of "nosave" pfn ranges, registered by
+ * architecture code, and used by swsusp when deciding what memory to
+ * save.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/rbtree.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
+
+struct nosave_extent {
+ struct rb_node rb_node;
+ unsigned long start;
+ unsigned long end;
+};
+
+static spinlock_t nosave_lock = SPIN_LOCK_UNLOCKED;
+static struct rb_root nosave_extents = RB_ROOT;
+
+#define rb_entry_extent(node) rb_entry(node, struct nosave_extent, rb_node)
+#define rb_next_extent(node) rb_entry_extent(rb_next(node))
+#define rb_prev_extent(node) rb_entry_extent(rb_prev(node))
+
+static int __is_nosave_region(unsigned long start_pfn, unsigned long end_pfn)
+{
+ struct rb_node *n = nosave_extents.rb_node;
+
+ BUG_ON(end_pfn < start_pfn);
+
+ while (n) {
+ struct nosave_extent *ext = rb_entry_extent(n);
+
+ if (start_pfn < ext->start) {
+ if (end_pfn >= ext->start)
+ return 1;
+ n = n->rb_left;
+ } else if (end_pfn > ext->end) {
+ if (start_pfn <= ext->end)
+ return 1;
+ n = n->rb_right;
+ } else
+ return 1;
+ }
+
+ return 0;
+}
+
+static int is_nosave_region(unsigned long start_pfn, unsigned long end_pfn)
+{
+ int ret;
+ spin_lock(&nosave_lock);
+ ret = __is_nosave_region(start_pfn, end_pfn);
+ spin_unlock(&nosave_lock);
+ return ret;
+}
+
+int __init register_nosave_region(unsigned long start_pfn, unsigned long end_pfn)
+{
+ struct rb_node **p = &nosave_extents.rb_node;
+ struct rb_node *parent = NULL;
+ struct nosave_extent *ext, *new_extent;
+ int ret = 0;
+
+ spin_lock(&nosave_lock);
+ if (__is_nosave_region(start_pfn, end_pfn)) {
+ ret = -EEXIST;
+ goto out;
+ }
+
+ new_extent = kmalloc(sizeof(struct nosave_extent), GFP_ATOMIC);
+ if (!new_extent) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ new_extent->start = start_pfn;
+ new_extent->end = end_pfn;
+
+ while (*p) {
+ parent = *p;
+ ext = rb_entry_extent(parent);
+
+ if (start_pfn < ext->start)
+ p = &(*p)->rb_left;
+ else if (start_pfn > ext->start)
+ p = &(*p)->rb_right;
+ else
+ BUG();
+ }
+
+ rb_link_node(&new_extent->rb_node, parent, p);
+ rb_insert_color(&new_extent->rb_node, &nosave_extents);
+
+out:
+ spin_unlock(&nosave_lock);
+ return ret;
+}
+
+int is_nosave_pfn(unsigned long pfn)
+{
+ return is_nosave_region(pfn, pfn);
+}
Index: linux-2.6/kernel/power/power.h
===================================================================
--- linux-2.6.orig/kernel/power/power.h 2007-03-02 01:51:08.000000000 +1100
+++ linux-2.6/kernel/power/power.h 2007-03-02 02:06:07.000000000 +1100
@@ -15,6 +15,7 @@ struct swsusp_info {
#ifdef CONFIG_SOFTWARE_SUSPEND
extern int pm_suspend_disk(void);
+extern int is_nosave_pfn(unsigned long pfn);
#else
static inline int pm_suspend_disk(void)
Index: linux-2.6/kernel/power/snapshot.c
===================================================================
--- linux-2.6.orig/kernel/power/snapshot.c 2007-03-02 01:51:08.000000000 +1100
+++ linux-2.6/kernel/power/snapshot.c 2007-03-02 02:16:10.000000000 +1100
@@ -47,17 +47,15 @@ static void *buffer;
/**
* @safe_needed - on resume, for storing the PBE list and the image,
* we can only use memory pages that do not conflict with the pages
- * used before suspend. The unsafe pages have PageNosaveFree set
- * and we count them using unsafe_pages.
+ * saved before suspend. mark_saved_pages finds these and marks them
+ * with PageSwsuspSaved.
*
- * Each allocated image page is marked as PageNosave and PageNosaveFree
- * so that swsusp_free() can release it.
+ * Each allocated image page is marked as PageSwsuspImage so that
+ * swsusp_free() will release it.
*/
#define PG_ANY 0
#define PG_SAFE 1
-#define PG_UNSAFE_CLEAR 1
-#define PG_UNSAFE_KEEP 0
static unsigned int allocated_unsafe_pages;
@@ -66,21 +64,24 @@ static void *get_image_page(gfp_t gfp_ma
void *res;
res = (void *)get_zeroed_page(gfp_mask);
- if (safe_needed)
- while (res && PageNosaveFree(virt_to_page(res))) {
- /* The page is unsafe, mark it for swsusp_free() */
- SetPageNosave(virt_to_page(res));
+#if 0
+ if (safe_needed) /* XXX: should _always_ allocate "safe" pages */
+#endif
+ while (res && PageSwsuspSaved(virt_to_page(res))) {
+ /*
+ * Not actually an image page, but we must mark it
+ * as such for swsusp_free()
+ */
+ SetPageSwsuspImage(virt_to_page(res));
allocated_unsafe_pages++;
res = (void *)get_zeroed_page(gfp_mask);
}
- if (res) {
- SetPageNosave(virt_to_page(res));
- SetPageNosaveFree(virt_to_page(res));
- }
+ if (res)
+ SetPageSwsuspImage(virt_to_page(res));
return res;
}
-unsigned long get_safe_page(gfp_t gfp_mask)
+unsigned long get_safe_page(gfp_t gfp_mask) /* XXX: used in arch code */
{
return (unsigned long)get_image_page(gfp_mask, PG_SAFE);
}
@@ -90,10 +91,8 @@ static struct page *alloc_image_page(gfp
struct page *page;
page = alloc_page(gfp_mask);
- if (page) {
- SetPageNosave(page);
- SetPageNosaveFree(page);
- }
+ if (page)
+ SetPageSwsuspImage(page);
return page;
}
@@ -102,7 +101,7 @@ static struct page *alloc_image_page(gfp
* get_image_page (page flags set by it must be cleared)
*/
-static inline void free_image_page(void *addr, int clear_nosave_free)
+static inline void free_image_page(void *addr)
{
struct page *page;
@@ -110,9 +109,8 @@ static inline void free_image_page(void
page = virt_to_page(addr);
- ClearPageNosave(page);
- if (clear_nosave_free)
- ClearPageNosaveFree(page);
+ BUG_ON(!PageSwsuspImage(page));
+ ClearPageSwsuspImage(page);
__free_page(page);
}
@@ -127,12 +125,12 @@ struct linked_page {
} __attribute__((packed));
static inline void
-free_list_of_pages(struct linked_page *list, int clear_page_nosave)
+free_list_of_pages(struct linked_page *list)
{
while (list) {
struct linked_page *lp = list->next;
- free_image_page(list, clear_page_nosave);
+ free_image_page(list);
list = lp;
}
}
@@ -188,9 +186,9 @@ static void *chain_alloc(struct chain_al
return ret;
}
-static void chain_free(struct chain_allocator *ca, int clear_page_nosave)
+static void chain_free(struct chain_allocator *ca)
{
- free_list_of_pages(ca->chain, clear_page_nosave);
+ free_list_of_pages(ca->chain);
memset(ca, 0, sizeof(struct chain_allocator));
}
@@ -289,7 +287,7 @@ static void memory_bm_position_reset(str
memory_bm_reset_chunk(bm);
}
-static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free);
+static void memory_bm_free(struct memory_bitmap *bm);
/**
* create_bm_block_list - create a list of block bitmap objects
@@ -360,7 +358,7 @@ memory_bm_create(struct memory_bitmap *b
zone_bm = create_zone_bm_list(nr, &ca);
bm->zone_bm_list = zone_bm;
if (!zone_bm) {
- chain_free(&ca, PG_UNSAFE_CLEAR);
+ chain_free(&ca);
return -ENOMEM;
}
@@ -413,7 +411,7 @@ memory_bm_create(struct memory_bitmap *b
Free:
bm->p_list = ca.chain;
- memory_bm_free(bm, PG_UNSAFE_CLEAR);
+ memory_bm_free(bm);
return -ENOMEM;
}
@@ -421,7 +419,7 @@ memory_bm_create(struct memory_bitmap *b
* memory_bm_free - free memory occupied by the memory bitmap @bm
*/
-static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free)
+static void memory_bm_free(struct memory_bitmap *bm)
{
struct zone_bitmap *zone_bm;
@@ -433,12 +431,12 @@ static void memory_bm_free(struct memory
bb = zone_bm->bm_blocks;
while (bb) {
if (bb->data)
- free_image_page(bb->data, clear_nosave_free);
+ free_image_page(bb->data);
bb = bb->next;
}
zone_bm = zone_bm->next;
}
- free_list_of_pages(bm->p_list, clear_nosave_free);
+ free_list_of_pages(bm->p_list);
bm->zone_bm_list = NULL;
}
@@ -600,8 +598,9 @@ static unsigned int count_free_highmem_p
* saveable_highmem_page - Determine whether a highmem page should be
* included in the suspend image.
*
- * We should save the page if it isn't Nosave or NosaveFree, or Reserved,
- * and it isn't a part of a free chunk of pages.
+ * We should save the page if it isn't in a nosave_pfn region, and if
+ * it isn't already free (page_count()==0), and if it isn't part of our
+ * suspend image.
*/
static struct page *saveable_highmem_page(unsigned long pfn)
@@ -611,11 +610,22 @@ static struct page *saveable_highmem_pag
if (!pfn_valid(pfn))
return NULL;
+ if (is_nosave_pfn(pfn))
+ return NULL;
+
page = pfn_to_page(pfn);
BUG_ON(!PageHighMem(page));
- if (PageNosave(page) || PageReserved(page) || PageNosaveFree(page))
+ /* XXX: this is racy if there is other stuff running... we
+ * could just use the free page count to estimate this for
+ * use in shrink_memory.
+ */
+ if (page_count(page) == 0)
+ return NULL;
+
+ /* XXX: really need to check PageReserved? */
+ if (PageReserved(page) || PageSwsuspImage(page))
return NULL;
return page;
@@ -637,7 +647,6 @@ unsigned int count_highmem_pages(void)
if (!is_highmem(zone))
continue;
- mark_free_pages(zone);
max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
if (saveable_highmem_page(pfn))
@@ -651,23 +660,11 @@ static inline unsigned int count_highmem
#endif /* CONFIG_HIGHMEM */
/**
- * pfn_is_nosave - check if given pfn is in the 'nosave' section
- */
-
-static inline int pfn_is_nosave(unsigned long pfn)
-{
- unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
- unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT;
- return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
-}
-
-/**
* saveable - Determine whether a non-highmem page should be included in
* the suspend image.
*
- * We should save the page if it isn't Nosave, and is not in the range
- * of pages statically defined as 'unsaveable', and it isn't a part of
- * a free chunk of pages.
+ * We should save the page based on criteria similar to
+ * saveable_highmem_page.
*/
static struct page *saveable_page(unsigned long pfn)
@@ -677,14 +674,17 @@ static struct page *saveable_page(unsign
if (!pfn_valid(pfn))
return NULL;
+ if (is_nosave_pfn(pfn))
+ return NULL;
+
page = pfn_to_page(pfn);
BUG_ON(PageHighMem(page));
- if (PageNosave(page) || PageNosaveFree(page))
+ if (page_count(page) == 0)
return NULL;
- if (PageReserved(page) && pfn_is_nosave(pfn))
+ if (PageSwsuspImage(page))
return NULL;
return page;
@@ -705,7 +705,6 @@ unsigned int count_data_pages(void)
if (is_highmem(zone))
continue;
- mark_free_pages(zone);
max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
if(saveable_page(pfn))
@@ -783,11 +782,14 @@ copy_data_pages(struct memory_bitmap *co
for_each_zone(zone) {
unsigned long max_zone_pfn;
- mark_free_pages(zone);
max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
- for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
- if (page_is_saveable(zone, pfn))
+ for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) {
+ struct page *page = page_is_saveable(zone, pfn);
+ if (page) {
+ SetPageSwsuspSaved(page);
memory_bm_set_bit(orig_bm, pfn);
+ }
+ }
}
memory_bm_position_reset(orig_bm);
memory_bm_position_reset(copy_bm);
@@ -821,9 +823,10 @@ void swsusp_free(void)
if (pfn_valid(pfn)) {
struct page *page = pfn_to_page(pfn);
- if (PageNosave(page) && PageNosaveFree(page)) {
- ClearPageNosave(page);
- ClearPageNosaveFree(page);
+ if (PageSwsuspSaved(page))
+ ClearPageSwsuspSaved(page);
+ if (PageSwsuspImage(page)) {
+ ClearPageSwsuspImage(page);
__free_page(page);
}
}
@@ -1131,22 +1134,21 @@ int snapshot_read_next(struct snapshot_h
}
/**
- * mark_unsafe_pages - mark the pages that cannot be used for storing
+ * mark_saved_pages - mark the pages that cannot be used for storing
* the image during resume, because they conflict with the pages that
- * had been used before suspend
+ * had been in use before suspending (ie. they were "saved").
*/
-static int mark_unsafe_pages(struct memory_bitmap *bm)
+static int mark_saved_pages(struct memory_bitmap *bm)
{
struct zone *zone;
unsigned long pfn, max_zone_pfn;
- /* Clear page flags */
+ /* Check page flags */
for_each_zone(zone) {
max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
- if (pfn_valid(pfn))
- ClearPageNosaveFree(pfn_to_page(pfn));
+ WARN_ON(pfn_valid(pfn) && PageSwsuspSaved(pfn_to_page(pfn)));
}
/* Mark pages that correspond to the "original" pfns as "unsafe" */
@@ -1155,7 +1157,7 @@ static int mark_unsafe_pages(struct memo
pfn = memory_bm_next_pfn(bm);
if (likely(pfn != BM_END_OF_MAP)) {
if (likely(pfn_valid(pfn)))
- SetPageNosaveFree(pfn_to_page(pfn));
+ SetPageSwsuspSaved(pfn_to_page(pfn));
else
return -EFAULT;
}
@@ -1321,14 +1323,13 @@ prepare_highmem_image(struct memory_bitm
struct page *page;
page = alloc_page(__GFP_HIGHMEM);
- if (!PageNosaveFree(page)) {
+ if (!PageSwsuspSaved(page)) {
/* The page is "safe", set its bit the bitmap */
memory_bm_set_bit(bm, page_to_pfn(page));
safe_highmem_pages++;
}
/* Mark the page as allocated */
- SetPageNosave(page);
- SetPageNosaveFree(page);
+ SetPageSwsuspImage(page);
}
memory_bm_position_reset(bm);
safe_highmem_bm = bm;
@@ -1360,7 +1361,7 @@ get_highmem_page_buffer(struct page *pag
struct highmem_pbe *pbe;
void *kaddr;
- if (PageNosave(page) && PageNosaveFree(page)) {
+ if (PageSwsuspSaved(page) && PageSwsuspImage(page)) {
/* We have allocated the "original" page frame and we can
* use it directly to store the loaded page.
*/
@@ -1422,10 +1423,10 @@ static inline int last_highmem_page_copi
static inline void free_highmem_data(void)
{
if (safe_highmem_bm)
- memory_bm_free(safe_highmem_bm, PG_UNSAFE_CLEAR);
+ memory_bm_free(safe_highmem_bm);
if (buffer)
- free_image_page(buffer, PG_UNSAFE_CLEAR);
+ free_image_page(buffer);
}
#else
static inline int get_safe_write_buffer(void) { return 0; }
@@ -1474,11 +1475,11 @@ prepare_image(struct memory_bitmap *new_
int error;
/* If there is no highmem, the buffer will not be necessary */
- free_image_page(buffer, PG_UNSAFE_CLEAR);
+ free_image_page(buffer);
buffer = NULL;
nr_highmem = count_highmem_image_pages(bm);
- error = mark_unsafe_pages(bm);
+ error = mark_saved_pages(bm);
if (error)
goto Free;
@@ -1487,7 +1488,8 @@ prepare_image(struct memory_bitmap *new_
goto Free;
duplicate_memory_bitmap(new_bm, bm);
- memory_bm_free(bm, PG_UNSAFE_KEEP);
+ memory_bm_free(bm);
+
if (nr_highmem > 0) {
error = prepare_highmem_image(bm, &nr_highmem);
if (error)
@@ -1522,20 +1524,19 @@ prepare_image(struct memory_bitmap *new_
error = -ENOMEM;
goto Free;
}
- if (!PageNosaveFree(virt_to_page(lp))) {
+ if (!PageSwsuspSaved(virt_to_page(lp))) {
/* The page is "safe", add it to the list */
lp->next = safe_pages_list;
safe_pages_list = lp;
}
/* Mark the page as allocated */
- SetPageNosave(virt_to_page(lp));
- SetPageNosaveFree(virt_to_page(lp));
+ SetPageSwsuspImage(virt_to_page(lp));
nr_pages--;
}
/* Free the reserved safe pages so that chain_alloc() can use them */
while (sp_list) {
lp = sp_list->next;
- free_image_page(sp_list, PG_UNSAFE_CLEAR);
+ free_image_page(sp_list);
sp_list = lp;
}
return 0;
@@ -1558,7 +1559,7 @@ static void *get_buffer(struct memory_bi
if (PageHighMem(page))
return get_highmem_page_buffer(page, ca);
- if (PageNosave(page) && PageNosaveFree(page))
+ if (PageSwsuspSaved(page) && PageSwsuspImage(page))
/* We have allocated the "original" page frame and we can
* use it directly to store the loaded page.
*/
@@ -1680,7 +1681,7 @@ void snapshot_write_finalize(struct snap
copy_last_highmem_page();
/* Free only if we have loaded the image entirely */
if (handle->prev && handle->cur > nr_meta_pages + nr_copy_pages) {
- memory_bm_free(&orig_bm, PG_UNSAFE_CLEAR);
+ memory_bm_free(&orig_bm);
free_highmem_data();
}
}
@@ -1733,7 +1734,7 @@ int restore_highmem(void)
swap_two_pages_data(pbe->copy_page, pbe->orig_page, buf);
pbe = pbe->next;
}
- free_image_page(buf, PG_UNSAFE_CLEAR);
+ free_image_page(buf);
return 0;
}
#endif /* CONFIG_HIGHMEM */
Index: linux-2.6/arch/x86_64/kernel/e820.c
===================================================================
--- linux-2.6.orig/arch/x86_64/kernel/e820.c 2007-03-02 01:51:09.000000000 +1100
+++ linux-2.6/arch/x86_64/kernel/e820.c 2007-03-02 02:06:07.000000000 +1100
@@ -259,16 +259,12 @@ void __init e820_reserve_resources(void)
static void __init
e820_mark_nosave_range(unsigned long start, unsigned long end)
{
- unsigned long pfn, max_pfn;
-
if (start >= end)
return;
printk("Nosave address range: %016lx - %016lx\n", start, end);
- max_pfn = end >> PAGE_SHIFT;
- for (pfn = start >> PAGE_SHIFT; pfn < max_pfn; pfn++)
- if (pfn_valid(pfn))
- SetPageNosave(pfn_to_page(pfn));
+ if (register_nosave_region(start >> PAGE_SHIFT, end >> PAGE_SHIFT))
+ panic("Could not register nosave region\n");
}
/*
Index: linux-2.6/include/linux/page-flags.h
===================================================================
--- linux-2.6.orig/include/linux/page-flags.h 2007-03-02 01:51:08.000000000 +1100
+++ linux-2.6/include/linux/page-flags.h 2007-03-02 02:06:07.000000000 +1100
@@ -82,14 +82,15 @@
#define PG_private 11 /* If pagecache, has fs-private data */
#define PG_writeback 12 /* Page is under writeback */
-#define PG_nosave 13 /* Used for system suspend/resume */
-#define PG_compound 14 /* Part of a compound page */
-#define PG_swapcache 15 /* Swap page: swp_entry_t in private */
-
-#define PG_mappedtodisk 16 /* Has blocks allocated on-disk */
-#define PG_reclaim 17 /* To be reclaimed asap */
-#define PG_nosave_free 18 /* Used for system suspend/resume */
-#define PG_buddy 19 /* Page is free, on buddy lists */
+#define PG_compound 13 /* Part of a compound page */
+#define PG_swapcache 14 /* Swap page: swp_entry_t in private */
+#define PG_mappedtodisk 15 /* Has blocks allocated on-disk */
+
+#define PG_reclaim 16 /* To be reclaimed asap */
+#define PG_buddy 17 /* Page is free, on buddy lists */
+
+#define PG_swsusp_image 18
+#define PG_swsusp_saved 19
/* PG_owner_priv_1 users should have descriptive aliases */
#define PG_checked PG_owner_priv_1 /* Used by some filesystems */
@@ -214,15 +215,13 @@ static inline void SetPageUptodate(struc
ret; \
})
-#define PageNosave(page) test_bit(PG_nosave, &(page)->flags)
-#define SetPageNosave(page) set_bit(PG_nosave, &(page)->flags)
-#define TestSetPageNosave(page) test_and_set_bit(PG_nosave, &(page)->flags)
-#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 PageSwsuspImage(page) test_bit(PG_swsusp_image, &(page)->flags)
+#define SetPageSwsuspImage(page) set_bit(PG_swsusp_image, &(page)->flags)
+#define ClearPageSwsuspImage(page) clear_bit(PG_swsusp_image, &(page)->flags)
+
+#define PageSwsuspSaved(page) test_bit(PG_swsusp_saved, &(page)->flags)
+#define SetPageSwsuspSaved(page) set_bit(PG_swsusp_saved, &(page)->flags)
+#define ClearPageSwsuspSaved(page) clear_bit(PG_swsusp_saved, &(page)->flags)
#define PageBuddy(page) test_bit(PG_buddy, &(page)->flags)
#define __SetPageBuddy(page) __set_bit(PG_buddy, &(page)->flags)
Index: linux-2.6/kernel/power/main.c
===================================================================
--- linux-2.6.orig/kernel/power/main.c 2007-03-02 01:51:09.000000000 +1100
+++ linux-2.6/kernel/power/main.c 2007-03-02 02:06:07.000000000 +1100
@@ -334,6 +334,10 @@ static int __init pm_init(void)
int error = subsystem_register(&power_subsys);
if (!error)
error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+ if (!error)
+ error = register_nosave_region(
+ __pa(&__nosave_begin) >> PAGE_SHIFT,
+ PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT);
return error;
}
Index: linux-2.6/mm/page_alloc.c
===================================================================
--- linux-2.6.orig/mm/page_alloc.c 2007-03-02 01:51:09.000000000 +1100
+++ linux-2.6/mm/page_alloc.c 2007-03-02 02:06:07.000000000 +1100
@@ -752,40 +752,6 @@ static void __drain_pages(unsigned int c
}
#ifdef CONFIG_PM
-
-void mark_free_pages(struct zone *zone)
-{
- unsigned long pfn, max_zone_pfn;
- unsigned long flags;
- int order;
- struct list_head *curr;
-
- if (!zone->spanned_pages)
- return;
-
- spin_lock_irqsave(&zone->lock, flags);
-
- max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
- for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
- if (pfn_valid(pfn)) {
- struct page *page = pfn_to_page(pfn);
-
- if (!PageNosave(page))
- ClearPageNosaveFree(page);
- }
-
- for (order = MAX_ORDER - 1; order >= 0; --order)
- list_for_each(curr, &zone->free_area[order].free_list) {
- unsigned long i;
-
- pfn = page_to_pfn(list_entry(curr, struct page, lru));
- for (i = 0; i < (1UL << order); i++)
- SetPageNosaveFree(pfn_to_page(pfn + i));
- }
-
- spin_unlock_irqrestore(&zone->lock, flags);
-}
-
/*
* Spill all of this CPU's per-cpu pages back into the buddy allocator.
*/
next prev parent reply other threads:[~2007-03-01 15:18 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-02-16 10:13 Christoph Lameter
2007-02-16 10:56 ` Rafael J. Wysocki
2007-02-28 10:14 ` Pavel Machek
2007-02-28 15:25 ` Christoph Lameter
2007-02-28 17:13 ` Rafael J. Wysocki
2007-02-28 17:17 ` Christoph Lameter
2007-02-28 17:33 ` Rafael J. Wysocki
2007-02-28 17:35 ` Christoph Lameter
2007-02-28 17:51 ` Rafael J. Wysocki
2007-02-28 17:56 ` Christoph Lameter
2007-02-28 21:11 ` Pavel Machek
2007-03-01 2:35 ` Nick Piggin
2007-03-01 15:18 ` Nick Piggin [this message]
2007-03-01 15:33 ` Rafael J. Wysocki
2007-03-01 23:10 ` Rafael J. Wysocki
2007-03-04 13:50 ` [RFC][PATCH 0/3] swsusp: Do not use page flags (was: Re: Remove page flags for software suspend) Rafael J. Wysocki
2007-03-04 14:07 ` [RFC][PATCH 1/3] swsusp: Do not use page flags directly Rafael J. Wysocki
2007-03-13 4:45 ` Nick Piggin
2007-03-04 14:07 ` [RFC][PATCH 2/3] swsusp: Do not use page flags Rafael J. Wysocki
2007-03-13 4:47 ` Nick Piggin
2007-03-13 9:16 ` Rafael J. Wysocki
2007-03-13 9:23 ` Nick Piggin
2007-03-13 10:17 ` Rafael J. Wysocki
2007-03-13 10:31 ` Nick Piggin
2007-03-13 21:20 ` Rafael J. Wysocki
2007-03-14 3:17 ` Nick Piggin
2007-03-14 8:30 ` Rafael J. Wysocki
2007-03-04 14:08 ` [RFC][PATCH 3/3] mm: Remove nosave and nosave_free " Rafael J. Wysocki
2007-03-08 1:00 ` [RFC][PATCH 0/3] swsusp: Do not use page flags (was: Re: Remove page flags for software suspend) Johannes Berg
2007-03-08 22:05 ` Rafael J. Wysocki
2007-03-08 22:10 ` Johannes Berg
2007-03-08 22:33 ` Rafael J. Wysocki
2007-03-08 22:43 ` Johannes Berg
2007-03-08 22:54 ` Rafael J. Wysocki
2007-03-08 22:54 ` Johannes Berg
2007-03-08 23:15 ` Pavel Machek
2007-03-08 23:21 ` Johannes Berg
2007-03-08 23:23 ` Pavel Machek
2007-03-08 23:34 ` Rafael J. Wysocki
2007-03-08 23:36 ` Pavel Machek
2007-03-08 15:09 ` Johannes Berg
2007-03-08 22:10 ` Rafael J. Wysocki
2007-03-08 22:12 ` Johannes Berg
2007-03-08 15:53 ` Peter Zijlstra
2007-03-08 22:11 ` Rafael J. Wysocki
2007-03-01 17:48 ` Remove page flags for software suspend Hugh Dickins
2007-03-13 3:36 ` Nick Piggin
2007-03-01 20:46 ` Rafael J. Wysocki
2007-03-02 10:17 ` Pavel Machek
2007-02-28 21:08 ` Pavel Machek
2007-02-28 21:16 ` Christoph Lameter
2007-02-28 21:22 ` Pavel Machek
2007-02-28 22:23 ` Rafael J. Wysocki
2007-03-01 2:31 ` Nick Piggin
2007-02-28 10:14 ` 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=45E6EEC5.4060902@yahoo.com.au \
--to=nickpiggin@yahoo.com.au \
--cc=clameter@engr.sgi.com \
--cc=linux-mm@kvack.org \
--cc=pavel@ucw.cz \
--cc=rjw@sisk.pl \
/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