|
@@ -735,6 +735,13 @@ static void __free_pages_ok(struct page *page, unsigned int order)
|
|
|
local_irq_restore(flags);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Read access to zone->managed_pages is safe because it's unsigned long,
|
|
|
+ * but we still need to serialize writers. Currently all callers of
|
|
|
+ * __free_pages_bootmem() except put_page_bootmem() should only be used
|
|
|
+ * at boot time. So for shorter boot time, we shift the burden to
|
|
|
+ * put_page_bootmem() to serialize writers.
|
|
|
+ */
|
|
|
void __meminit __free_pages_bootmem(struct page *page, unsigned int order)
|
|
|
{
|
|
|
unsigned int nr_pages = 1 << order;
|
|
@@ -750,6 +757,7 @@ void __meminit __free_pages_bootmem(struct page *page, unsigned int order)
|
|
|
set_page_count(p, 0);
|
|
|
}
|
|
|
|
|
|
+ page_zone(page)->managed_pages += 1 << order;
|
|
|
set_page_refcounted(page);
|
|
|
__free_pages(page, order);
|
|
|
}
|
|
@@ -2984,6 +2992,7 @@ void show_free_areas(unsigned int filter)
|
|
|
" isolated(anon):%lukB"
|
|
|
" isolated(file):%lukB"
|
|
|
" present:%lukB"
|
|
|
+ " managed:%lukB"
|
|
|
" mlocked:%lukB"
|
|
|
" dirty:%lukB"
|
|
|
" writeback:%lukB"
|
|
@@ -3013,6 +3022,7 @@ void show_free_areas(unsigned int filter)
|
|
|
K(zone_page_state(zone, NR_ISOLATED_ANON)),
|
|
|
K(zone_page_state(zone, NR_ISOLATED_FILE)),
|
|
|
K(zone->present_pages),
|
|
|
+ K(zone->managed_pages),
|
|
|
K(zone_page_state(zone, NR_MLOCK)),
|
|
|
K(zone_page_state(zone, NR_FILE_DIRTY)),
|
|
|
K(zone_page_state(zone, NR_WRITEBACK)),
|
|
@@ -4502,48 +4512,54 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
|
|
|
|
|
|
for (j = 0; j < MAX_NR_ZONES; j++) {
|
|
|
struct zone *zone = pgdat->node_zones + j;
|
|
|
- unsigned long size, realsize, memmap_pages;
|
|
|
+ unsigned long size, realsize, freesize, memmap_pages;
|
|
|
|
|
|
size = zone_spanned_pages_in_node(nid, j, zones_size);
|
|
|
- realsize = size - zone_absent_pages_in_node(nid, j,
|
|
|
+ realsize = freesize = size - zone_absent_pages_in_node(nid, j,
|
|
|
zholes_size);
|
|
|
|
|
|
/*
|
|
|
- * Adjust realsize so that it accounts for how much memory
|
|
|
+ * Adjust freesize so that it accounts for how much memory
|
|
|
* is used by this zone for memmap. This affects the watermark
|
|
|
* and per-cpu initialisations
|
|
|
*/
|
|
|
memmap_pages =
|
|
|
PAGE_ALIGN(size * sizeof(struct page)) >> PAGE_SHIFT;
|
|
|
- if (realsize >= memmap_pages) {
|
|
|
- realsize -= memmap_pages;
|
|
|
+ if (freesize >= memmap_pages) {
|
|
|
+ freesize -= memmap_pages;
|
|
|
if (memmap_pages)
|
|
|
printk(KERN_DEBUG
|
|
|
" %s zone: %lu pages used for memmap\n",
|
|
|
zone_names[j], memmap_pages);
|
|
|
} else
|
|
|
printk(KERN_WARNING
|
|
|
- " %s zone: %lu pages exceeds realsize %lu\n",
|
|
|
- zone_names[j], memmap_pages, realsize);
|
|
|
+ " %s zone: %lu pages exceeds freesize %lu\n",
|
|
|
+ zone_names[j], memmap_pages, freesize);
|
|
|
|
|
|
/* Account for reserved pages */
|
|
|
- if (j == 0 && realsize > dma_reserve) {
|
|
|
- realsize -= dma_reserve;
|
|
|
+ if (j == 0 && freesize > dma_reserve) {
|
|
|
+ freesize -= dma_reserve;
|
|
|
printk(KERN_DEBUG " %s zone: %lu pages reserved\n",
|
|
|
zone_names[0], dma_reserve);
|
|
|
}
|
|
|
|
|
|
if (!is_highmem_idx(j))
|
|
|
- nr_kernel_pages += realsize;
|
|
|
- nr_all_pages += realsize;
|
|
|
+ nr_kernel_pages += freesize;
|
|
|
+ nr_all_pages += freesize;
|
|
|
|
|
|
zone->spanned_pages = size;
|
|
|
- zone->present_pages = realsize;
|
|
|
+ zone->present_pages = freesize;
|
|
|
+ /*
|
|
|
+ * Set an approximate value for lowmem here, it will be adjusted
|
|
|
+ * when the bootmem allocator frees pages into the buddy system.
|
|
|
+ * And all highmem pages will be managed by the buddy system.
|
|
|
+ */
|
|
|
+ zone->managed_pages = is_highmem_idx(j) ? realsize : freesize;
|
|
|
#ifdef CONFIG_NUMA
|
|
|
zone->node = nid;
|
|
|
- zone->min_unmapped_pages = (realsize*sysctl_min_unmapped_ratio)
|
|
|
+ zone->min_unmapped_pages = (freesize*sysctl_min_unmapped_ratio)
|
|
|
/ 100;
|
|
|
- zone->min_slab_pages = (realsize * sysctl_min_slab_ratio) / 100;
|
|
|
+ zone->min_slab_pages = (freesize * sysctl_min_slab_ratio) / 100;
|
|
|
#endif
|
|
|
zone->name = zone_names[j];
|
|
|
spin_lock_init(&zone->lock);
|