Re: [PATCH] do not count pages in holes with sparsemem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 6 Jul 2006 17:05:35 +0200, "Franck Bui-Huu" <vagabon.xyz@xxxxxxxxx> wrote:
> >         free_area_init_node(0, NODE_DATA(0), zones_size, 0, zholes_size);
> > +#else
> > +       free_area_init_node(0, NODE_DATA(0), zones_size, ARCH_PFN_OFFSET, NULL);
> 
> which is equivalent to:
> 
>        free_area_init(zones_size);

Sure.  Then this can be a final proposal?


With some memory model other than FLATMEM, the single node can
contains some holes so there might be many invalid pages.  For
example, with two 256M memory and one 256M hole, some variables
(num_physpage, totalpages, nr_kernel_pages, nr_all_pages, etc.) will
indicate that there are 768MB on this system.  This is not desired
because, for example, alloc_large_system_hash() allocates too many
entries.

Use free_area_init_node() with counted zholes_size[] instead of
free_area_init().

For num_physpages, use number of ram pages instead of max_low_pfn.

Signed-off-by: Atsushi Nemoto <anemo@xxxxxxxxxxxxx>

diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 802bdd3..c52497b 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -139,10 +139,36 @@ #endif /* CONFIG_HIGHMEM */
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 extern void pagetable_init(void);
 
+static int __init page_is_ram(unsigned long pagenr)
+{
+	int i;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		unsigned long addr, end;
+
+		if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
+			/* not usable memory */
+			continue;
+
+		addr = PFN_UP(boot_mem_map.map[i].addr);
+		end = PFN_DOWN(boot_mem_map.map[i].addr +
+			       boot_mem_map.map[i].size);
+
+		if (pagenr >= addr && pagenr < end)
+			return 1;
+	}
+
+	return 0;
+}
+
 void __init paging_init(void)
 {
-	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+	unsigned long zones_size[] = { [0 ... MAX_NR_ZONES - 1] = 0 };
 	unsigned long max_dma, high, low;
+#ifndef CONFIG_FLATMEM
+	unsigned long zholes_size[] = { [0 ... MAX_NR_ZONES - 1] = 0 };
+	unsigned long i, j, pfn;
+#endif
 
 	pagetable_init();
 
@@ -174,29 +200,16 @@ #ifdef CONFIG_HIGHMEM
 		zones_size[ZONE_HIGHMEM] = high - low;
 #endif
 
+#ifdef CONFIG_FLATMEM
 	free_area_init(zones_size);
-}
-
-static inline int page_is_ram(unsigned long pagenr)
-{
-	int i;
-
-	for (i = 0; i < boot_mem_map.nr_map; i++) {
-		unsigned long addr, end;
-
-		if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
-			/* not usable memory */
-			continue;
-
-		addr = PFN_UP(boot_mem_map.map[i].addr);
-		end = PFN_DOWN(boot_mem_map.map[i].addr +
-			       boot_mem_map.map[i].size);
-
-		if (pagenr >= addr && pagenr < end)
-			return 1;
-	}
-
-	return 0;
+#else
+	pfn = 0;
+	for (i = 0; i < MAX_NR_ZONES; i++)
+		for (j = 0; j < zones_size[i]; j++, pfn++)
+			if (!page_is_ram(pfn))
+				zholes_size[i]++;
+	free_area_init_node(0, NODE_DATA(0), zones_size, 0, zholes_size);
+#endif
 }
 
 static struct kcore_list kcore_mem, kcore_vmalloc;
@@ -213,9 +226,9 @@ #ifdef CONFIG_HIGHMEM
 #ifdef CONFIG_DISCONTIGMEM
 #error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet"
 #endif
-	max_mapnr = num_physpages = highend_pfn;
+	max_mapnr = highend_pfn;
 #else
-	max_mapnr = num_physpages = max_low_pfn;
+	max_mapnr = max_low_pfn;
 #endif
 	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 
@@ -229,6 +242,7 @@ #endif
 			if (PageReserved(pfn_to_page(tmp)))
 				reservedpages++;
 		}
+	num_physpages = ram;
 
 #ifdef CONFIG_HIGHMEM
 	for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) {
@@ -247,6 +261,7 @@ #endif
 		totalhigh_pages++;
 	}
 	totalram_pages += totalhigh_pages;
+	num_physpages += totalhigh_pages;
 #endif
 
 	codesize =  (unsigned long) &_etext - (unsigned long) &_text;


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux