aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory_hotplug.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r--mm/memory_hotplug.c83
1 files changed, 44 insertions, 39 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 656ad1c65422..833f854eabe5 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -159,17 +159,58 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat)
159} 159}
160#endif /* !CONFIG_SPARSEMEM_VMEMMAP */ 160#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
161 161
162static void grow_zone_span(struct zone *zone, unsigned long start_pfn,
163 unsigned long end_pfn)
164{
165 unsigned long old_zone_end_pfn;
166
167 zone_span_writelock(zone);
168
169 old_zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
170 if (start_pfn < zone->zone_start_pfn)
171 zone->zone_start_pfn = start_pfn;
172
173 zone->spanned_pages = max(old_zone_end_pfn, end_pfn) -
174 zone->zone_start_pfn;
175
176 zone_span_writeunlock(zone);
177}
178
179static void grow_pgdat_span(struct pglist_data *pgdat, unsigned long start_pfn,
180 unsigned long end_pfn)
181{
182 unsigned long old_pgdat_end_pfn =
183 pgdat->node_start_pfn + pgdat->node_spanned_pages;
184
185 if (start_pfn < pgdat->node_start_pfn)
186 pgdat->node_start_pfn = start_pfn;
187
188 pgdat->node_spanned_pages = max(old_pgdat_end_pfn, end_pfn) -
189 pgdat->node_start_pfn;
190}
191
162static int __add_zone(struct zone *zone, unsigned long phys_start_pfn) 192static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
163{ 193{
164 struct pglist_data *pgdat = zone->zone_pgdat; 194 struct pglist_data *pgdat = zone->zone_pgdat;
165 int nr_pages = PAGES_PER_SECTION; 195 int nr_pages = PAGES_PER_SECTION;
166 int nid = pgdat->node_id; 196 int nid = pgdat->node_id;
167 int zone_type; 197 int zone_type;
198 unsigned long flags;
168 199
169 zone_type = zone - pgdat->node_zones; 200 zone_type = zone - pgdat->node_zones;
170 if (!zone->wait_table) 201 if (!zone->wait_table) {
171 return init_currently_empty_zone(zone, phys_start_pfn, 202 int ret;
172 nr_pages, MEMMAP_HOTPLUG); 203
204 ret = init_currently_empty_zone(zone, phys_start_pfn,
205 nr_pages, MEMMAP_HOTPLUG);
206 if (ret)
207 return ret;
208 }
209 pgdat_resize_lock(zone->zone_pgdat, &flags);
210 grow_zone_span(zone, phys_start_pfn, phys_start_pfn + nr_pages);
211 grow_pgdat_span(zone->zone_pgdat, phys_start_pfn,
212 phys_start_pfn + nr_pages);
213 pgdat_resize_unlock(zone->zone_pgdat, &flags);
173 memmap_init_zone(nr_pages, nid, zone_type, 214 memmap_init_zone(nr_pages, nid, zone_type,
174 phys_start_pfn, MEMMAP_HOTPLUG); 215 phys_start_pfn, MEMMAP_HOTPLUG);
175 return 0; 216 return 0;
@@ -295,36 +336,6 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
295} 336}
296EXPORT_SYMBOL_GPL(__remove_pages); 337EXPORT_SYMBOL_GPL(__remove_pages);
297 338
298static void grow_zone_span(struct zone *zone,
299 unsigned long start_pfn, unsigned long end_pfn)
300{
301 unsigned long old_zone_end_pfn;
302
303 zone_span_writelock(zone);
304
305 old_zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
306 if (start_pfn < zone->zone_start_pfn)
307 zone->zone_start_pfn = start_pfn;
308
309 zone->spanned_pages = max(old_zone_end_pfn, end_pfn) -
310 zone->zone_start_pfn;
311
312 zone_span_writeunlock(zone);
313}
314
315static void grow_pgdat_span(struct pglist_data *pgdat,
316 unsigned long start_pfn, unsigned long end_pfn)
317{
318 unsigned long old_pgdat_end_pfn =
319 pgdat->node_start_pfn + pgdat->node_spanned_pages;
320
321 if (start_pfn < pgdat->node_start_pfn)
322 pgdat->node_start_pfn = start_pfn;
323
324 pgdat->node_spanned_pages = max(old_pgdat_end_pfn, end_pfn) -
325 pgdat->node_start_pfn;
326}
327
328void online_page(struct page *page) 339void online_page(struct page *page)
329{ 340{
330 totalram_pages++; 341 totalram_pages++;
@@ -363,7 +374,6 @@ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
363 374
364int online_pages(unsigned long pfn, unsigned long nr_pages) 375int online_pages(unsigned long pfn, unsigned long nr_pages)
365{ 376{
366 unsigned long flags;
367 unsigned long onlined_pages = 0; 377 unsigned long onlined_pages = 0;
368 struct zone *zone; 378 struct zone *zone;
369 int need_zonelists_rebuild = 0; 379 int need_zonelists_rebuild = 0;
@@ -391,11 +401,6 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
391 * memory_block->state_mutex. 401 * memory_block->state_mutex.
392 */ 402 */
393 zone = page_zone(pfn_to_page(pfn)); 403 zone = page_zone(pfn_to_page(pfn));
394 pgdat_resize_lock(zone->zone_pgdat, &flags);
395 grow_zone_span(zone, pfn, pfn + nr_pages);
396 grow_pgdat_span(zone->zone_pgdat, pfn, pfn + nr_pages);
397 pgdat_resize_unlock(zone->zone_pgdat, &flags);
398
399 /* 404 /*
400 * If this zone is not populated, then it is not in zonelist. 405 * If this zone is not populated, then it is not in zonelist.
401 * This means the page allocator ignores this zone. 406 * This means the page allocator ignores this zone.