Unverified Commit 6cea0048 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!2793 handle uninitialized numa nodes gracefully.

Merge Pull Request from: @ci-robot 
 
PR sync from: Wupeng Ma <mawupeng1@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/QP5QADEIWBBOYYMYKJ6GV2S7USQE5Q6Z/ 
From: Ma Wupeng <mawupeng1@huawei.com>

handle uninitialized numa nodes gracefully.

Michal Hocko (2):
  mm, memory_hotplug: make arch_alloc_nodedata independent on
    CONFIG_MEMORY_HOTPLUG
  mm: handle uninitialized numa nodes gracefully

Oscar Salvador (1):
  arch/x86/mm/numa: Do not initialize nodes twice


-- 
2.25.1
 
https://gitee.com/openeuler/kernel/issues/I8EPOJ 
 
Link:https://gitee.com/openeuler/kernel/pulls/2793

 

Reviewed-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
Reviewed-by: default avatarLiu YongQiang <liuyongqiang13@huawei.com>
Signed-off-by: default avatarZhang Changzhong <zhangchangzhong@huawei.com>
parents e102a105 cbce63a0
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -631,12 +631,11 @@ void __init paging_init(void)
	zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
}

#ifdef CONFIG_MEMORY_HOTPLUG
pg_data_t *arch_alloc_nodedata(int nid)
pg_data_t * __init arch_alloc_nodedata(int nid)
{
	unsigned long size = compute_pernodesize(nid);

	return kzalloc(size, GFP_KERNEL);
	return _va(memblock_alloc(size, SMP_CACHE_BYTES));
}

void arch_free_nodedata(pg_data_t *pgdat)
@@ -649,7 +648,6 @@ void arch_refresh_nodedata(int update_node, pg_data_t *update_pgdat)
	pgdat_list[update_node] = update_pgdat;
	scatter_node_data();
}
#endif

#ifdef CONFIG_SPARSEMEM_VMEMMAP
int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
+10 −16
Original line number Diff line number Diff line
@@ -722,21 +722,6 @@ void __init x86_numa_init(void)
	numa_init(dummy_numa_init);
}

static void __init init_memory_less_node(int nid)
{
	unsigned long zones_size[MAX_NR_ZONES] = {0};
	unsigned long zholes_size[MAX_NR_ZONES] = {0};

	/* Allocate and initialize node data. Memory-less node is now online.*/
	alloc_node_data(nid);
	free_area_init_node(nid, zones_size, 0, zholes_size);

	/*
	 * All zonelists will be built later in start_kernel() after per cpu
	 * areas are initialized.
	 */
}

/*
 * Setup early cpu_to_node.
 *
@@ -764,8 +749,17 @@ void __init init_cpu_to_node(void)
		if (node == NUMA_NO_NODE)
			continue;

		/*
		 * Exclude this node from
		 * bringup_nonboot_cpus
		 *  cpu_up
		 *   __try_online_node
		 *    register_one_node
		 * because node_subsys is not initialized yet.
		 * TODO remove dependency on node_online
		 */
		if (!node_online(node))
			init_memory_less_node(node);
			node_set_online(node);

		numa_set_node(cpu, node);
	}
+60 −60
Original line number Diff line number Diff line
@@ -15,6 +15,66 @@ struct memory_block;
struct resource;
struct vmem_altmap;

#ifdef CONFIG_HAVE_ARCH_NODEDATA_EXTENSION
/*
 * For supporting node-hotadd, we have to allocate a new pgdat.
 *
 * If an arch has generic style NODE_DATA(),
 * node_data[nid] = kzalloc() works well. But it depends on the architecture.
 *
 * In general, generic_alloc_nodedata() is used.
 * Now, arch_free_nodedata() is just defined for error path of node_hot_add.
 *
 */
extern pg_data_t *arch_alloc_nodedata(int nid);
extern void arch_free_nodedata(pg_data_t *pgdat);
extern void arch_refresh_nodedata(int nid, pg_data_t *pgdat);

#else /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */

#define arch_alloc_nodedata(nid)	generic_alloc_nodedata(nid)
#define arch_free_nodedata(pgdat)	generic_free_nodedata(pgdat)

#ifdef CONFIG_NUMA
/*
 * XXX: node aware allocation can't work well to get new node's memory at this time.
 *	Because, pgdat for the new node is not allocated/initialized yet itself.
 *	To use new node's memory, more consideration will be necessary.
 */
#define generic_alloc_nodedata(nid)				\
({								\
	__va(memblock_alloc(sizeof(*pgdat), SMP_CACHE_BYTES));	\
})
/*
 * This definition is just for error path in node hotadd.
 * For node hotremove, we have to replace this.
 */
#define generic_free_nodedata(pgdat)	kfree(pgdat)

extern pg_data_t *node_data[];
static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
{
	node_data[nid] = pgdat;
}

#else /* !CONFIG_NUMA */

/* never called */
static inline pg_data_t *generic_alloc_nodedata(int nid)
{
	BUG();
	return NULL;
}
static inline void generic_free_nodedata(pg_data_t *pgdat)
{
}
static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
{
}
#endif /* CONFIG_NUMA */
#endif /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */


#ifdef CONFIG_MEMORY_HOTPLUG
/*
 * Return page for the valid pfn only if the page is online. All pfn
@@ -146,66 +206,6 @@ static inline int memory_add_physaddr_to_nid(u64 start)
}
#endif

#ifdef CONFIG_HAVE_ARCH_NODEDATA_EXTENSION
/*
 * For supporting node-hotadd, we have to allocate a new pgdat.
 *
 * If an arch has generic style NODE_DATA(),
 * node_data[nid] = kzalloc() works well. But it depends on the architecture.
 *
 * In general, generic_alloc_nodedata() is used.
 * Now, arch_free_nodedata() is just defined for error path of node_hot_add.
 *
 */
extern pg_data_t *arch_alloc_nodedata(int nid);
extern void arch_free_nodedata(pg_data_t *pgdat);
extern void arch_refresh_nodedata(int nid, pg_data_t *pgdat);

#else /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */

#define arch_alloc_nodedata(nid)	generic_alloc_nodedata(nid)
#define arch_free_nodedata(pgdat)	generic_free_nodedata(pgdat)

#ifdef CONFIG_NUMA
/*
 * If ARCH_HAS_NODEDATA_EXTENSION=n, this func is used to allocate pgdat.
 * XXX: kmalloc_node() can't work well to get new node's memory at this time.
 *	Because, pgdat for the new node is not allocated/initialized yet itself.
 *	To use new node's memory, more consideration will be necessary.
 */
#define generic_alloc_nodedata(nid)				\
({								\
	kzalloc(sizeof(pg_data_t), GFP_KERNEL);			\
})
/*
 * This definition is just for error path in node hotadd.
 * For node hotremove, we have to replace this.
 */
#define generic_free_nodedata(pgdat)	kfree(pgdat)

extern pg_data_t *node_data[];
static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
{
	node_data[nid] = pgdat;
}

#else /* !CONFIG_NUMA */

/* never called */
static inline pg_data_t *generic_alloc_nodedata(int nid)
{
	BUG();
	return NULL;
}
static inline void generic_free_nodedata(pg_data_t *pgdat)
{
}
static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
{
}
#endif /* CONFIG_NUMA */
#endif /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */

#ifdef CONFIG_HAVE_BOOTMEM_INFO_NODE
extern void __init register_page_bootmem_info_node(struct pglist_data *pgdat);
#else
+2 −0
Original line number Diff line number Diff line
@@ -614,4 +614,6 @@ extern int is_pagecache_reading_kernel_recovery_enable(void);
extern int is_get_user_kernel_recovery_enable(void);
#endif

DECLARE_PER_CPU(struct per_cpu_nodestat, boot_nodestats);

#endif	/* __MM_INTERNAL_H */
+10 −14
Original line number Diff line number Diff line
@@ -920,18 +920,20 @@ static void reset_node_present_pages(pg_data_t *pgdat)
}

/* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */
static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
static pg_data_t __ref *hotadd_init_pgdat(int nid, u64 start)
{
	struct pglist_data *pgdat;
	unsigned long start_pfn = PFN_DOWN(start);

	pgdat = NODE_DATA(nid);
	if (!pgdat) {
		pgdat = arch_alloc_nodedata(nid);
		if (!pgdat)
			return NULL;

		arch_refresh_nodedata(nid, pgdat);
	/*
	 * NODE_DATA is preallocated (free_area_init) but its internal
	 * state is not allocated completely. Add missing pieces.
	 * Completely offline nodes stay around and they just need
	 * reintialization.
	 */
	if (pgdat->per_cpu_nodestats == &boot_nodestats) {
	} else {
		/*
		 * Reset the nr_zones, order and classzone_idx before reuse.
@@ -943,10 +945,7 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
		pgdat->kswapd_classzone_idx = 0;
	}

	/* we can use NODE_DATA(nid) from here */

	pgdat->node_id = nid;
	pgdat->node_start_pfn = start_pfn;
	pgdat->node_start_pfn = 0;

	/* init node's zones as empty zones, we don't have any present pages.*/
	free_area_init_core_hotplug(nid);
@@ -1000,7 +999,7 @@ static int __try_online_node(int nid, u64 start, bool set_node_online)
	if (node_online(nid))
		return 0;

	pgdat = hotadd_new_pgdat(nid, start);
	pgdat = hotadd_init_pgdat(nid, start);
	if (!pgdat) {
		pr_err("Cannot online node %d due to NULL pgdat\n", nid);
		ret = -ENOMEM;
@@ -1123,9 +1122,6 @@ int __ref add_memory_resource(int nid, struct resource *res)

	return ret;
error:
	/* rollback pgdat allocation and others */
	if (new_node)
		rollback_node_hotadd(nid);
	memblock_remove(start, size);
	mem_hotplug_done();
	return ret;
Loading