aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/memory_hotplug.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 6cdeabe9f6d4..83d37a401b3b 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -164,13 +164,65 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
164 return 0; 164 return 0;
165} 165}
166 166
167static pg_data_t *hotadd_new_pgdat(int nid, u64 start)
168{
169 struct pglist_data *pgdat;
170 unsigned long zones_size[MAX_NR_ZONES] = {0};
171 unsigned long zholes_size[MAX_NR_ZONES] = {0};
172 unsigned long start_pfn = start >> PAGE_SHIFT;
173
174 pgdat = arch_alloc_nodedata(nid);
175 if (!pgdat)
176 return NULL;
177
178 arch_refresh_nodedata(nid, pgdat);
179
180 /* we can use NODE_DATA(nid) from here */
181
182 /* init node's zones as empty zones, we don't have any present pages.*/
183 free_area_init_node(nid, pgdat, zones_size, start_pfn, zholes_size);
184
185 return pgdat;
186}
187
188static void rollback_node_hotadd(int nid, pg_data_t *pgdat)
189{
190 arch_refresh_nodedata(nid, NULL);
191 arch_free_nodedata(pgdat);
192 return;
193}
194
167int add_memory(int nid, u64 start, u64 size) 195int add_memory(int nid, u64 start, u64 size)
168{ 196{
197 pg_data_t *pgdat = NULL;
198 int new_pgdat = 0;
169 int ret; 199 int ret;
170 200
201 if (!node_online(nid)) {
202 pgdat = hotadd_new_pgdat(nid, start);
203 if (!pgdat)
204 return -ENOMEM;
205 new_pgdat = 1;
206 ret = kswapd_run(nid);
207 if (ret)
208 goto error;
209 }
210
171 /* call arch's memory hotadd */ 211 /* call arch's memory hotadd */
172 ret = arch_add_memory(nid, start, size); 212 ret = arch_add_memory(nid, start, size);
173 213
214 if (ret < 0)
215 goto error;
216
217 /* we online node here. we have no error path from here. */
218 node_set_online(nid);
219
220 return ret;
221error:
222 /* rollback pgdat allocation and others */
223 if (new_pgdat)
224 rollback_node_hotadd(nid, pgdat);
225
174 return ret; 226 return ret;
175} 227}
176EXPORT_SYMBOL_GPL(add_memory); 228EXPORT_SYMBOL_GPL(add_memory);