mem-hotplug: reset node managed pages when hot-adding a new pgdat
In free_area_init_core(), zone->managed_pages is set to an approximate value for lowmem, and will be adjusted when the bootmem allocator frees pages into the buddy system. But free_area_init_core() is also called by hotadd_new_pgdat() when hot-adding memory. As a result, zone->managed_pages of the newly added node's pgdat is set to an approximate value in the very beginning. Even if the memory on that node has node been onlined, /sys/device/system/node/nodeXXX/meminfo has wrong value: hot-add node2 (memory not onlined) cat /sys/device/system/node/node2/meminfo Node 2 MemTotal: 33554432 kB Node 2 MemFree: 0 kB Node 2 MemUsed: 33554432 kB Node 2 Active: 0 kB This patch fixes this problem by reset node managed pages to 0 after hot-adding a new node. 1. Move reset_managed_pages_done from reset_node_managed_pages() to reset_all_zones_managed_pages() 2. Make reset_node_managed_pages() non-static 3. Call reset_node_managed_pages() in hotadd_new_pgdat() after pgdat is initialized Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com> Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Cc: <stable@vger.kernel.org> [3.16+] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
57cbc87e03
commit
f784a3f196
|
@ -46,6 +46,7 @@ extern unsigned long init_bootmem_node(pg_data_t *pgdat,
|
|||
extern unsigned long init_bootmem(unsigned long addr, unsigned long memend);
|
||||
|
||||
extern unsigned long free_all_bootmem(void);
|
||||
extern void reset_node_managed_pages(pg_data_t *pgdat);
|
||||
extern void reset_all_zones_managed_pages(void);
|
||||
|
||||
extern void free_bootmem_node(pg_data_t *pgdat,
|
||||
|
|
|
@ -243,13 +243,10 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
|
|||
|
||||
static int reset_managed_pages_done __initdata;
|
||||
|
||||
static inline void __init reset_node_managed_pages(pg_data_t *pgdat)
|
||||
void reset_node_managed_pages(pg_data_t *pgdat)
|
||||
{
|
||||
struct zone *z;
|
||||
|
||||
if (reset_managed_pages_done)
|
||||
return;
|
||||
|
||||
for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
|
||||
z->managed_pages = 0;
|
||||
}
|
||||
|
@ -258,8 +255,12 @@ void __init reset_all_zones_managed_pages(void)
|
|||
{
|
||||
struct pglist_data *pgdat;
|
||||
|
||||
if (reset_managed_pages_done)
|
||||
return;
|
||||
|
||||
for_each_online_pgdat(pgdat)
|
||||
reset_node_managed_pages(pgdat);
|
||||
|
||||
reset_managed_pages_done = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/stop_machine.h>
|
||||
#include <linux/hugetlb.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/bootmem.h>
|
||||
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
|
@ -1096,6 +1097,14 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
|
|||
build_all_zonelists(pgdat, NULL);
|
||||
mutex_unlock(&zonelists_mutex);
|
||||
|
||||
/*
|
||||
* zone->managed_pages is set to an approximate value in
|
||||
* free_area_init_core(), which will cause
|
||||
* /sys/device/system/node/nodeX/meminfo has wrong data.
|
||||
* So reset it to 0 before any memory is onlined.
|
||||
*/
|
||||
reset_node_managed_pages(pgdat);
|
||||
|
||||
return pgdat;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,12 +145,10 @@ static unsigned long __init free_low_memory_core_early(void)
|
|||
|
||||
static int reset_managed_pages_done __initdata;
|
||||
|
||||
static inline void __init reset_node_managed_pages(pg_data_t *pgdat)
|
||||
void reset_node_managed_pages(pg_data_t *pgdat)
|
||||
{
|
||||
struct zone *z;
|
||||
|
||||
if (reset_managed_pages_done)
|
||||
return;
|
||||
for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
|
||||
z->managed_pages = 0;
|
||||
}
|
||||
|
@ -159,8 +157,12 @@ void __init reset_all_zones_managed_pages(void)
|
|||
{
|
||||
struct pglist_data *pgdat;
|
||||
|
||||
if (reset_managed_pages_done)
|
||||
return;
|
||||
|
||||
for_each_online_pgdat(pgdat)
|
||||
reset_node_managed_pages(pgdat);
|
||||
|
||||
reset_managed_pages_done = 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue