[PATCH] wait_table and zonelist initializing for memory hotadd: add return code for...
[linux-2.6-block.git] / mm / memory_hotplug.c
index 2e916c308ae6278c4fc05aab3591d785e173131d..71da5c98c9c1ad6284ddcbb4845df266335003e3 100644 (file)
@@ -26,7 +26,7 @@
 
 extern void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn,
                          unsigned long size);
-static void __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;
        int nr_pages = PAGES_PER_SECTION;
@@ -34,15 +34,21 @@ static void __add_zone(struct zone *zone, unsigned long phys_start_pfn)
        int zone_type;
 
        zone_type = zone - pgdat->node_zones;
+       if (!populated_zone(zone)) {
+               int ret = 0;
+               ret = init_currently_empty_zone(zone, phys_start_pfn, nr_pages);
+               if (ret < 0)
+                       return ret;
+       }
        memmap_init_zone(nr_pages, nid, zone_type, phys_start_pfn);
        zonetable_add(zone, nid, zone_type, phys_start_pfn, nr_pages);
+       return 0;
 }
 
 extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
                                  int nr_pages);
 static int __add_section(struct zone *zone, unsigned long phys_start_pfn)
 {
-       struct pglist_data *pgdat = zone->zone_pgdat;
        int nr_pages = PAGES_PER_SECTION;
        int ret;
 
@@ -51,7 +57,11 @@ static int __add_section(struct zone *zone, unsigned long phys_start_pfn)
        if (ret < 0)
                return ret;
 
-       __add_zone(zone, phys_start_pfn);
+       ret = __add_zone(zone, phys_start_pfn);
+
+       if (ret < 0)
+               return ret;
+
        return register_new_memory(__pfn_to_section(phys_start_pfn));
 }
 
@@ -70,12 +80,16 @@ int __add_pages(struct zone *zone, unsigned long phys_start_pfn,
        for (i = 0; i < nr_pages; i += PAGES_PER_SECTION) {
                err = __add_section(zone, phys_start_pfn + i);
 
-               if (err)
+               /* We want to keep adding the rest of the
+                * sections if the first ones already exist
+                */
+               if (err && (err != -EEXIST))
                        break;
        }
 
        return err;
 }
+EXPORT_SYMBOL_GPL(__add_pages);
 
 static void grow_zone_span(struct zone *zone,
                unsigned long start_pfn, unsigned long end_pfn)
@@ -88,8 +102,8 @@ static void grow_zone_span(struct zone *zone,
        if (start_pfn < zone->zone_start_pfn)
                zone->zone_start_pfn = start_pfn;
 
-       if (end_pfn > old_zone_end_pfn)
-               zone->spanned_pages = end_pfn - zone->zone_start_pfn;
+       zone->spanned_pages = max(old_zone_end_pfn, end_pfn) -
+                               zone->zone_start_pfn;
 
        zone_span_writeunlock(zone);
 }
@@ -103,8 +117,8 @@ static void grow_pgdat_span(struct pglist_data *pgdat,
        if (start_pfn < pgdat->node_start_pfn)
                pgdat->node_start_pfn = start_pfn;
 
-       if (end_pfn > old_pgdat_end_pfn)
-               pgdat->node_spanned_pages = end_pfn - pgdat->node_spanned_pages;
+       pgdat->node_spanned_pages = max(old_pgdat_end_pfn, end_pfn) -
+                                       pgdat->node_start_pfn;
 }
 
 int online_pages(unsigned long pfn, unsigned long nr_pages)
@@ -131,6 +145,9 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
                onlined_pages++;
        }
        zone->present_pages += onlined_pages;
+       zone->zone_pgdat->node_present_pages += onlined_pages;
+
+       setup_per_zone_pages_min();
 
        return 0;
 }