Subject: [PATCH] memblock: Free allocated memblock.memory.regions We could allocate that too. So free it like reserved.regions. For x86_64, need to move absent_page calculating early. Signed-off-by: Yinghai Lu --- arch/x86/mm/init_64.c | 4 +++- include/linux/memblock.h | 1 + mm/memblock.c | 23 ++++++++++++++++++----- mm/nobootmem.c | 5 +++++ 4 files changed, 27 insertions(+), 6 deletions(-) Index: linux-2.6/arch/x86/mm/init_64.c =================================================================== --- linux-2.6.orig/arch/x86/mm/init_64.c +++ linux-2.6/arch/x86/mm/init_64.c @@ -690,6 +690,9 @@ void __init mem_init(void) reservedpages = 0; + /* get that before num_free_all_bootmem, it will free memory.regions */ + absent_pages = absent_pages_in_range(0, max_pfn); + /* this will put all low memory onto the freelists */ #ifdef CONFIG_NUMA totalram_pages = numa_free_all_bootmem(); @@ -697,7 +700,6 @@ void __init mem_init(void) totalram_pages = free_all_bootmem(); #endif - absent_pages = absent_pages_in_range(0, max_pfn); reservedpages = max_pfn - totalram_pages - absent_pages; after_bootmem = 1; Index: linux-2.6/include/linux/memblock.h =================================================================== --- linux-2.6.orig/include/linux/memblock.h +++ linux-2.6/include/linux/memblock.h @@ -51,6 +51,7 @@ phys_addr_t memblock_find_in_range_node( phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end, phys_addr_t size, phys_addr_t align); phys_addr_t get_allocated_memblock_reserved_regions_info(phys_addr_t *addr); +phys_addr_t get_allocated_memblock_memory_regions_info(phys_addr_t *addr); void memblock_allow_resize(void); int memblock_add_node(phys_addr_t base, phys_addr_t size, int nid); int memblock_add(phys_addr_t base, phys_addr_t size); Index: linux-2.6/mm/memblock.c =================================================================== --- linux-2.6.orig/mm/memblock.c +++ linux-2.6/mm/memblock.c @@ -160,16 +160,29 @@ static void __init_memblock memblock_rem } } -phys_addr_t __init_memblock get_allocated_memblock_reserved_regions_info( +static phys_addr_t __init_memblock get_allocated_memblock_regions_info( + struct memblock_type *type, phys_addr_t *addr) { - if (memblock.reserved.regions == memblock_reserved_init_regions) + if (type->regions == memblock_memory_init_regions || + type->regions == memblock_reserved_init_regions) return 0; - *addr = __pa(memblock.reserved.regions); + *addr = __pa(type->regions); + + return PAGE_ALIGN(sizeof(struct memblock_region) * type->max); +} + +phys_addr_t __init_memblock get_allocated_memblock_reserved_regions_info( + phys_addr_t *addr) +{ + return get_allocated_memblock_regions_info(&memblock.reserved, addr); +} - return PAGE_ALIGN(sizeof(struct memblock_region) * - memblock.reserved.max); +phys_addr_t __init_memblock get_allocated_memblock_memory_regions_info( + phys_addr_t *addr) +{ + return get_allocated_memblock_regions_info(&memblock.memory, addr); } /** Index: linux-2.6/mm/nobootmem.c =================================================================== --- linux-2.6.orig/mm/nobootmem.c +++ linux-2.6/mm/nobootmem.c @@ -134,6 +134,11 @@ unsigned long __init free_low_memory_cor if (size) count += __free_memory_core(start, start + size); + /* free range that is used for memory array if we allocate it */ + size = get_allocated_memblock_memory_regions_info(&start); + if (size) + count += __free_memory_core(start, start + size); + return count; }