|
@@ -159,17 +159,58 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat)
|
|
}
|
|
}
|
|
#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
|
|
#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
|
|
|
|
|
|
|
|
+static void grow_zone_span(struct zone *zone, unsigned long start_pfn,
|
|
|
|
+ unsigned long end_pfn)
|
|
|
|
+{
|
|
|
|
+ unsigned long old_zone_end_pfn;
|
|
|
|
+
|
|
|
|
+ zone_span_writelock(zone);
|
|
|
|
+
|
|
|
|
+ old_zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
|
|
|
|
+ if (start_pfn < zone->zone_start_pfn)
|
|
|
|
+ zone->zone_start_pfn = start_pfn;
|
|
|
|
+
|
|
|
|
+ zone->spanned_pages = max(old_zone_end_pfn, end_pfn) -
|
|
|
|
+ zone->zone_start_pfn;
|
|
|
|
+
|
|
|
|
+ zone_span_writeunlock(zone);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void grow_pgdat_span(struct pglist_data *pgdat, unsigned long start_pfn,
|
|
|
|
+ unsigned long end_pfn)
|
|
|
|
+{
|
|
|
|
+ unsigned long old_pgdat_end_pfn =
|
|
|
|
+ pgdat->node_start_pfn + pgdat->node_spanned_pages;
|
|
|
|
+
|
|
|
|
+ if (start_pfn < pgdat->node_start_pfn)
|
|
|
|
+ pgdat->node_start_pfn = start_pfn;
|
|
|
|
+
|
|
|
|
+ pgdat->node_spanned_pages = max(old_pgdat_end_pfn, end_pfn) -
|
|
|
|
+ pgdat->node_start_pfn;
|
|
|
|
+}
|
|
|
|
+
|
|
static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
|
|
static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
|
|
{
|
|
{
|
|
struct pglist_data *pgdat = zone->zone_pgdat;
|
|
struct pglist_data *pgdat = zone->zone_pgdat;
|
|
int nr_pages = PAGES_PER_SECTION;
|
|
int nr_pages = PAGES_PER_SECTION;
|
|
int nid = pgdat->node_id;
|
|
int nid = pgdat->node_id;
|
|
int zone_type;
|
|
int zone_type;
|
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
zone_type = zone - pgdat->node_zones;
|
|
zone_type = zone - pgdat->node_zones;
|
|
- if (!zone->wait_table)
|
|
|
|
- return init_currently_empty_zone(zone, phys_start_pfn,
|
|
|
|
- nr_pages, MEMMAP_HOTPLUG);
|
|
|
|
|
|
+ if (!zone->wait_table) {
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ ret = init_currently_empty_zone(zone, phys_start_pfn,
|
|
|
|
+ nr_pages, MEMMAP_HOTPLUG);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+ pgdat_resize_lock(zone->zone_pgdat, &flags);
|
|
|
|
+ grow_zone_span(zone, phys_start_pfn, phys_start_pfn + nr_pages);
|
|
|
|
+ grow_pgdat_span(zone->zone_pgdat, phys_start_pfn,
|
|
|
|
+ phys_start_pfn + nr_pages);
|
|
|
|
+ pgdat_resize_unlock(zone->zone_pgdat, &flags);
|
|
memmap_init_zone(nr_pages, nid, zone_type,
|
|
memmap_init_zone(nr_pages, nid, zone_type,
|
|
phys_start_pfn, MEMMAP_HOTPLUG);
|
|
phys_start_pfn, MEMMAP_HOTPLUG);
|
|
return 0;
|
|
return 0;
|
|
@@ -295,36 +336,6 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(__remove_pages);
|
|
EXPORT_SYMBOL_GPL(__remove_pages);
|
|
|
|
|
|
-static void grow_zone_span(struct zone *zone,
|
|
|
|
- unsigned long start_pfn, unsigned long end_pfn)
|
|
|
|
-{
|
|
|
|
- unsigned long old_zone_end_pfn;
|
|
|
|
-
|
|
|
|
- zone_span_writelock(zone);
|
|
|
|
-
|
|
|
|
- old_zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
|
|
|
|
- if (start_pfn < zone->zone_start_pfn)
|
|
|
|
- zone->zone_start_pfn = start_pfn;
|
|
|
|
-
|
|
|
|
- zone->spanned_pages = max(old_zone_end_pfn, end_pfn) -
|
|
|
|
- zone->zone_start_pfn;
|
|
|
|
-
|
|
|
|
- zone_span_writeunlock(zone);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void grow_pgdat_span(struct pglist_data *pgdat,
|
|
|
|
- unsigned long start_pfn, unsigned long end_pfn)
|
|
|
|
-{
|
|
|
|
- unsigned long old_pgdat_end_pfn =
|
|
|
|
- pgdat->node_start_pfn + pgdat->node_spanned_pages;
|
|
|
|
-
|
|
|
|
- if (start_pfn < pgdat->node_start_pfn)
|
|
|
|
- pgdat->node_start_pfn = start_pfn;
|
|
|
|
-
|
|
|
|
- pgdat->node_spanned_pages = max(old_pgdat_end_pfn, end_pfn) -
|
|
|
|
- pgdat->node_start_pfn;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
void online_page(struct page *page)
|
|
void online_page(struct page *page)
|
|
{
|
|
{
|
|
totalram_pages++;
|
|
totalram_pages++;
|
|
@@ -363,7 +374,6 @@ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
|
|
|
|
|
|
int online_pages(unsigned long pfn, unsigned long nr_pages)
|
|
int online_pages(unsigned long pfn, unsigned long nr_pages)
|
|
{
|
|
{
|
|
- unsigned long flags;
|
|
|
|
unsigned long onlined_pages = 0;
|
|
unsigned long onlined_pages = 0;
|
|
struct zone *zone;
|
|
struct zone *zone;
|
|
int need_zonelists_rebuild = 0;
|
|
int need_zonelists_rebuild = 0;
|
|
@@ -391,11 +401,6 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
|
|
* memory_block->state_mutex.
|
|
* memory_block->state_mutex.
|
|
*/
|
|
*/
|
|
zone = page_zone(pfn_to_page(pfn));
|
|
zone = page_zone(pfn_to_page(pfn));
|
|
- pgdat_resize_lock(zone->zone_pgdat, &flags);
|
|
|
|
- grow_zone_span(zone, pfn, pfn + nr_pages);
|
|
|
|
- grow_pgdat_span(zone->zone_pgdat, pfn, pfn + nr_pages);
|
|
|
|
- pgdat_resize_unlock(zone->zone_pgdat, &flags);
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* If this zone is not populated, then it is not in zonelist.
|
|
* If this zone is not populated, then it is not in zonelist.
|
|
* This means the page allocator ignores this zone.
|
|
* This means the page allocator ignores this zone.
|