Skip to contentSkip to conversation

peeling off zone from physical memory layout [6/10] for each page in zone.

RFC New KAMEZAWA Hiroyuki 1 participant 1 message Feb 3, 2006

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

RFC 1/1 peeling off zone from physical memory layout [6/10] for each page in zone.

Some codes want to walk all page sturct in a zone. This patch addes for_each_page_in_zone() to help them.

Because memory_map_list is not sorted, page will appear in random way. If this is a problem, some fix will be needed.

include/linux/memorymap.h +37 -0
Index: hogehoge/include/linux/memorymap.h
===================================================================
@@ -40,4 +40,41 @@ static inline void memory_resize_unlock(
 #endif
 
 
+/*
+ * Rarely used, but some codes searchs all pages in zone.
+ * which is done just by pfn++ in old days.
+ * pfn_to_zone can be done by page_zone(pfn_to_page(page)), so memory_map
+ * doesn't support such ops.
+ */
+
+static inline struct page *next_page_in_zone(struct page *page, struct zone *z, void **iter)
+{
+	unsigned long pfn = page_to_pfn(page);
+	struct memory_map* ent = (struct memory_map *)*iter;
+	if (pfn + 1 < ent->end_pfn)
+		return pfn_to_page(pfn + 1);
+	list_for_each_entry_continue(ent, &memory_map_list, list) {
+		if (ent->zone == z)
+			return pfn_to_page(ent->start_pfn);
+	}
+	return NULL;
+}
+
+static inline unsigned long lookup_zone_page(struct zone *z, void **iter)
+{
+	struct memory_map *ent;
+	list_for_each_entry(ent, &memory_map_list, list) {
+		if (ent->zone == z) {
+			*iter = ent;
+			return ent->start_pfn;
+		}
+	}
+	BUG();
+}
+
+/* iter is void*.  memory resize lock has to be held.*/
+#define for_each_page_in_zone(p, z, iter)	\
+	for (p = pfn_to_page(lookup_zone_page( z, &iter)), iter=NULL; \
+	     p != NULL;\
+	     p = next_page_in_zone(p, z, &iter))
 #endif
mm/page_alloc.c +5 -3
Index: hogehoge/mm/page_alloc.c
===================================================================
@@ -643,7 +643,9 @@ static void __drain_pages(unsigned int c
 
 void mark_free_pages(struct zone *zone)
 {
-	unsigned long zone_pfn, flags;
+	struct page *page;
+	void *iter;
+	unsigned long flags;
 	int order;
 	struct list_head *curr;
 
@@ -651,8 +653,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, iter)
+		ClearPageNosaveFree(page);
 
 	for (order = MAX_ORDER - 1; order >= 0; --order)
 		list_for_each(curr, &zone->free_area[order].free_list) {
kernel/power/snapshot.c +26 -43

142 lines not on this page · raw message

kernel/power/swsusp.c +5 -4
Index: hogehoge/kernel/power/swsusp.c
===================================================================
@@ -60,6 +60,7 @@
 #include <linux/syscalls.h>
 #include <linux/highmem.h>
 #include <linux/bio.h>
+#include <linux/memorymap.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -673,6 +674,8 @@ static void mark_unsafe_pages(struct pbe
 {
 	struct zone *zone;
 	unsigned long zone_pfn;
+	struct page *page;
+	void *iter;
 	struct pbe *p;
 
 	if (!pblist) /* a sanity check */
@@ -680,10 +683,8 @@ static void mark_unsafe_pages(struct pbe
 
 	/* 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, iter)
+			ClearPageNosaveFree(page);
 	}
 
 	/* Mark orig addresses */

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>