|
@@ -1034,8 +1034,10 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
|
|
|
return pgdat;
|
|
|
}
|
|
|
|
|
|
-static void rollback_node_hotadd(int nid, pg_data_t *pgdat)
|
|
|
+static void rollback_node_hotadd(int nid)
|
|
|
{
|
|
|
+ pg_data_t *pgdat = NODE_DATA(nid);
|
|
|
+
|
|
|
arch_refresh_nodedata(nid, NULL);
|
|
|
free_percpu(pgdat->per_cpu_nodestats);
|
|
|
arch_free_nodedata(pgdat);
|
|
@@ -1046,28 +1048,48 @@ static void rollback_node_hotadd(int nid, pg_data_t *pgdat)
|
|
|
/**
|
|
|
* try_online_node - online a node if offlined
|
|
|
* @nid: the node ID
|
|
|
- *
|
|
|
+ * @start: start addr of the node
|
|
|
+ * @set_node_online: Whether we want to online the node
|
|
|
* called by cpu_up() to online a node without onlined memory.
|
|
|
+ *
|
|
|
+ * Returns:
|
|
|
+ * 1 -> a new node has been allocated
|
|
|
+ * 0 -> the node is already online
|
|
|
+ * -ENOMEM -> the node could not be allocated
|
|
|
*/
|
|
|
-int try_online_node(int nid)
|
|
|
+static int __try_online_node(int nid, u64 start, bool set_node_online)
|
|
|
{
|
|
|
- pg_data_t *pgdat;
|
|
|
- int ret;
|
|
|
+ pg_data_t *pgdat;
|
|
|
+ int ret = 1;
|
|
|
|
|
|
if (node_online(nid))
|
|
|
return 0;
|
|
|
|
|
|
- mem_hotplug_begin();
|
|
|
- pgdat = hotadd_new_pgdat(nid, 0);
|
|
|
+ pgdat = hotadd_new_pgdat(nid, start);
|
|
|
if (!pgdat) {
|
|
|
pr_err("Cannot online node %d due to NULL pgdat\n", nid);
|
|
|
ret = -ENOMEM;
|
|
|
goto out;
|
|
|
}
|
|
|
- node_set_online(nid);
|
|
|
- ret = register_one_node(nid);
|
|
|
- BUG_ON(ret);
|
|
|
+
|
|
|
+ if (set_node_online) {
|
|
|
+ node_set_online(nid);
|
|
|
+ ret = register_one_node(nid);
|
|
|
+ BUG_ON(ret);
|
|
|
+ }
|
|
|
out:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Users of this function always want to online/register the node
|
|
|
+ */
|
|
|
+int try_online_node(int nid)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ mem_hotplug_begin();
|
|
|
+ ret = __try_online_node(nid, 0, true);
|
|
|
mem_hotplug_done();
|
|
|
return ret;
|
|
|
}
|
|
@@ -1099,9 +1121,7 @@ static int online_memory_block(struct memory_block *mem, void *arg)
|
|
|
int __ref add_memory_resource(int nid, struct resource *res, bool online)
|
|
|
{
|
|
|
u64 start, size;
|
|
|
- pg_data_t *pgdat = NULL;
|
|
|
- bool new_pgdat;
|
|
|
- bool new_node;
|
|
|
+ bool new_node = false;
|
|
|
int ret;
|
|
|
|
|
|
start = res->start;
|
|
@@ -1111,11 +1131,6 @@ int __ref add_memory_resource(int nid, struct resource *res, bool online)
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- { /* Stupid hack to suppress address-never-null warning */
|
|
|
- void *p = NODE_DATA(nid);
|
|
|
- new_pgdat = !p;
|
|
|
- }
|
|
|
-
|
|
|
mem_hotplug_begin();
|
|
|
|
|
|
/*
|
|
@@ -1126,17 +1141,13 @@ int __ref add_memory_resource(int nid, struct resource *res, bool online)
|
|
|
*/
|
|
|
memblock_add_node(start, size, nid);
|
|
|
|
|
|
- new_node = !node_online(nid);
|
|
|
- if (new_node) {
|
|
|
- pgdat = hotadd_new_pgdat(nid, start);
|
|
|
- ret = -ENOMEM;
|
|
|
- if (!pgdat)
|
|
|
- goto error;
|
|
|
- }
|
|
|
+ ret = __try_online_node(nid, start, false);
|
|
|
+ if (ret < 0)
|
|
|
+ goto error;
|
|
|
+ new_node = ret;
|
|
|
|
|
|
/* call arch's memory hotadd */
|
|
|
ret = arch_add_memory(nid, start, size, NULL, true);
|
|
|
-
|
|
|
if (ret < 0)
|
|
|
goto error;
|
|
|
|
|
@@ -1180,8 +1191,8 @@ register_fail:
|
|
|
|
|
|
error:
|
|
|
/* rollback pgdat allocation and others */
|
|
|
- if (new_pgdat && pgdat)
|
|
|
- rollback_node_hotadd(nid, pgdat);
|
|
|
+ if (new_node)
|
|
|
+ rollback_node_hotadd(nid);
|
|
|
memblock_remove(start, size);
|
|
|
|
|
|
out:
|