From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
To: linux-mm@kvack.org
Subject: [RFC] memory-layout-free zones (for review) [1/3] for_each_page_in_zone()
Date: Thu, 23 Feb 2006 17:56:43 +0900 [thread overview]
Message-ID: <20060223175643.a685dfb3.kamezawa.hiroyu@jp.fujitsu.com> (raw)
Hi, I'm now modifing zone to be free from memory layout mainly
for memory-hotplug. This post is just for review.
By these patches, zone_start_pfn/zone_spanned_pages are removed.
I already posted removing zone_mem_map patch. So, a zone which a
page belongs to is determined just by what (pfn,range) is passed to
free_area_init_core().
These patches will change the meaning of zones from a range of pages
to a group of pages, but no real effect now.
I'm now considering to move page betweens zones and add new zone
as ZONE_EASYRCLM, which is not defined by the range.
(IMHO, ZONE_EMERGENCY can be implemented in clean way in future
rather than mempools.)
I'll post these to lkml if I'm ready.
--Kame
==
This patch defines for_each_page_in_zone(page, zone) macro.
This macro is useful for iterate over all (valid) pages in a zone.
Some of codes, especially kernel/power/snapshot.c, iterate over
all pages in zone. This patch can clean up them.
Signed-Off-By: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Index: node-hot-add2/include/linux/mmzone.h
===================================================================
--- node-hot-add2.orig/include/linux/mmzone.h
+++ node-hot-add2/include/linux/mmzone.h
@@ -474,6 +474,54 @@ static inline struct zone *next_zone(str
zone; \
zone = next_zone(zone))
+/*
+ * These inline function for for_each_page_in_zone can work
+ * even if CONFIG_SPARSEMEM=y.
+ */
+static inline struct page *first_page_in_zone(struct zone *zone)
+{
+ unsigned long start_pfn = zone->zone_start_pfn;
+ unsigned long i = 0;
+
+ if (!populated_zone(zone))
+ return NULL;
+
+ for (i = 0; i < zone->zone_spanned_pages; i++) {
+ if (pfn_valid(start_pfn + i))
+ break;
+ }
+ return pfn_to_page(start_pfn + i);
+}
+
+static inline struct page *next_page_in_zone(struct page *page,
+ struct zone *zone)
+{
+ unsigned long start_pfn = zone->zone_start_pfn;
+ unsigned long i = page_to_pfn(page) - start_pfn;
+
+ if (!populated_zone(zone))
+ return NULL;
+
+ for (i = i + 1; i < zone->zone_spanned_pages; i++) {
+ if (pfn_vlaid(start_pfn + i))
+ break;
+ }
+ if (i == zone->zone_spanned_pages)
+ return NULL;
+ return pfn_to_page(start_pfn + i);
+}
+
+/**
+ * for_each_page_in_zone -- helper macro to iterate over all pages in a zone.
+ * @page - pointer to page
+ * @zone - pointer to zone
+ *
+ */
+#define for_each_page_in_zone(page, zone) \
+ for (page = (first_page_in_zone((zone))); \
+ page; \
+ page = next_page_in_zone(page, (zone)));
+
#ifdef CONFIG_SPARSEMEM
#include <asm/sparsemem.h>
#endif
Index: node-hot-add2/mm/page_alloc.c
===================================================================
--- node-hot-add2.orig/mm/page_alloc.c
+++ node-hot-add2/mm/page_alloc.c
@@ -670,7 +670,8 @@ static void __drain_pages(unsigned int c
void mark_free_pages(struct zone *zone)
{
- unsigned long zone_pfn, flags;
+ struct page *page;
+ unsigned long flags;
int order;
struct list_head *curr;
@@ -678,8 +679,8 @@ void mark_free_pages(struct zone *zone)
return;
spin_lock_irqsave(&zone->lock, flags);
- for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
- ClearPageNosaveFree(pfn_to_page(zone_pfn + zone->zone_start_pfn));
+ for_each_page_in_zone(page, zone)
+ ClearPageNosaveFree(page);
for (order = MAX_ORDER - 1; order >= 0; --order)
list_for_each(curr, &zone->free_area[order].free_list) {
Index: node-hot-add2/kernel/power/snapshot.c
===================================================================
--- node-hot-add2.orig/kernel/power/snapshot.c
+++ node-hot-add2/kernel/power/snapshot.c
@@ -43,18 +43,12 @@ static unsigned long *buffer;
unsigned int count_highmem_pages(void)
{
struct zone *zone;
- unsigned long zone_pfn;
unsigned int n = 0;
-
+ struct page *page;
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);
+ for_each_page_in_zone(page, zone) {
if (PageReserved(page))
continue;
if (PageNosaveFree(page))
@@ -75,19 +69,15 @@ static struct highmem_page *highmem_copy
static int save_highmem_zone(struct zone *zone)
{
- unsigned long zone_pfn;
+ struct page *page;
mark_free_pages(zone);
- for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
- struct page *page;
+ for_each_page_in_zone(page , zone) {
struct highmem_page *save;
void *kaddr;
- unsigned long pfn = zone_pfn + zone->zone_start_pfn;
+ unsigned long pfn = page_to_pfn(page);
if (!(pfn%10000))
printk(".");
- if (!pfn_valid(pfn))
- continue;
- page = pfn_to_page(pfn);
/*
* This condition results from rvmalloc() sans vmalloc_32()
* and architectural memory reservations. This should be
@@ -167,15 +157,8 @@ static int pfn_is_nosave(unsigned long p
* isn't part of a free chunk of pages.
*/
-static int saveable(struct zone *zone, unsigned long *zone_pfn)
+static int saveable(struct page *page)
{
- unsigned long pfn = *zone_pfn + zone->zone_start_pfn;
- struct page *page;
-
- if (!pfn_valid(pfn))
- return 0;
-
- page = pfn_to_page(pfn);
BUG_ON(PageReserved(page) && PageNosave(page));
if (PageNosave(page))
return 0;
@@ -190,15 +173,15 @@ static int saveable(struct zone *zone, u
unsigned int count_data_pages(void)
{
struct zone *zone;
- unsigned long zone_pfn;
+ struct page *page;
unsigned int n = 0;
for_each_zone (zone) {
if (is_highmem(zone))
continue;
mark_free_pages(zone);
- for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
- n += saveable(zone, &zone_pfn);
+ for_each_page_in_zone(page, zone)
+ n += saveable(page);
}
return n;
}
@@ -206,9 +189,8 @@ unsigned int count_data_pages(void)
static void copy_data_pages(struct pbe *pblist)
{
struct zone *zone;
- unsigned long zone_pfn;
struct pbe *pbe, *p;
-
+ struct page *page;
pbe = pblist;
for_each_zone (zone) {
if (is_highmem(zone))
@@ -219,10 +201,9 @@ static void copy_data_pages(struct pbe *
SetPageNosaveFree(virt_to_page(p));
for_each_pbe (p, pblist)
SetPageNosaveFree(virt_to_page(p->address));
- for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
- if (saveable(zone, &zone_pfn)) {
+ for_each_page_in_zone(page, zone) {
+ if (saveable(page)) {
struct page *page;
- page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
BUG_ON(!pbe);
pbe->orig_address = (unsigned long)page_address(page);
/* copy_page is not usable for copying task structs. */
@@ -403,19 +384,15 @@ struct pbe *alloc_pagedir(unsigned int n
void swsusp_free(void)
{
struct zone *zone;
- unsigned long zone_pfn;
-
+ struct page *page;
for_each_zone(zone) {
- for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
- if (pfn_valid(zone_pfn + zone->zone_start_pfn)) {
- struct page *page;
- page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
- if (PageNosave(page) && PageNosaveFree(page)) {
- ClearPageNosave(page);
- ClearPageNosaveFree(page);
- free_page((long) page_address(page));
- }
+ for_each_page_in_zone(page, zone) {
+ if (PageNosave(page) && PageNosaveFree(page)) {
+ ClearPageNosave(page);
+ ClearPageNosaveFree(page);
+ free_page((long) page_address(page));
}
+ }
}
nr_copy_pages = 0;
nr_meta_pages = 0;
@@ -618,18 +595,16 @@ int snapshot_read_next(struct snapshot_h
static int mark_unsafe_pages(struct pbe *pblist)
{
struct zone *zone;
- unsigned long zone_pfn;
struct pbe *p;
+ struct page *page;
if (!pblist) /* a sanity check */
return -EINVAL;
/* Clear page flags */
for_each_zone (zone) {
- for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
- if (pfn_valid(zone_pfn + zone->zone_start_pfn))
- ClearPageNosaveFree(pfn_to_page(zone_pfn +
- zone->zone_start_pfn));
+ for_each_page_in_zone(page, zone)
+ ClearPageNosaveFree(page);
}
/* Mark orig addresses */
Index: node-hot-add2/arch/i386/mm/discontig.c
===================================================================
--- node-hot-add2.orig/arch/i386/mm/discontig.c
+++ node-hot-add2/arch/i386/mm/discontig.c
@@ -400,23 +400,15 @@ void __init set_highmem_pages_init(int b
struct page *page;
for_each_zone(zone) {
- unsigned long node_pfn, zone_start_pfn, zone_end_pfn;
-
if (!is_highmem(zone))
continue;
- zone_start_pfn = zone->zone_start_pfn;
- zone_end_pfn = zone_start_pfn + zone->spanned_pages;
-
- printk("Initializing %s for node %d (%08lx:%08lx)\n",
- zone->name, zone->zone_pgdat->node_id,
- zone_start_pfn, zone_end_pfn);
+ printk("Initializing %s for node %d\n",
+ zone->name, zone->zone_pgdat->node_id);
- for (node_pfn = zone_start_pfn; node_pfn < zone_end_pfn; node_pfn++) {
- if (!pfn_valid(node_pfn))
- continue;
- page = pfn_to_page(node_pfn);
- add_one_highpage_init(page, node_pfn, bad_ppro);
+ for_each_page_in_zone(page, zone) {
+ add_one_highpage_init(page,
+ page_to_pfn(page), bad_ppro);
}
}
totalram_pages += totalhigh_pages;
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next reply other threads:[~2006-02-23 8:57 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-02-23 8:56 KAMEZAWA Hiroyuki [this message]
2006-02-23 18:03 ` Dave Hansen
2006-02-23 23:45 ` KAMEZAWA Hiroyuki
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=20060223175643.a685dfb3.kamezawa.hiroyu@jp.fujitsu.com \
--to=kamezawa.hiroyu@jp.fujitsu.com \
--cc=linux-mm@kvack.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