diff options
Diffstat (limited to 'mm/memory_hotplug.c')
| -rw-r--r-- | mm/memory_hotplug.c | 83 |
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 | ||
| 162 | static 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 | |||
| 179 | static 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 | |||
| 162 | static int __add_zone(struct zone *zone, unsigned long phys_start_pfn) | 192 | static 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 | } |
| 296 | EXPORT_SYMBOL_GPL(__remove_pages); | 337 | EXPORT_SYMBOL_GPL(__remove_pages); |
| 297 | 338 | ||
| 298 | static 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 | |||
| 315 | static 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 | |||
| 328 | void online_page(struct page *page) | 339 | void 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 | ||
| 364 | int online_pages(unsigned long pfn, unsigned long nr_pages) | 375 | int 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. |
