Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=75884fb1c6388f3713ddcca662f3647b3129aaeb
Commit:     75884fb1c6388f3713ddcca662f3647b3129aaeb
Parent:     48f13bf3e742fca8aab87f6c39451d03bf5952d4
Author:     KAMEZAWA Hiroyuki <[EMAIL PROTECTED]>
AuthorDate: Tue Oct 16 01:26:10 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Tue Oct 16 09:43:01 2007 -0700

    memory unplug: memory hotplug cleanup
    
    A clean up patch for "scanning memory resource [start, end)" operation.
    
    Now, find_next_system_ram() function is used in memory hotplug, but this
    interface is not easy to use and codes are complicated.
    
    This patch adds walk_memory_resouce(start,len,arg,func) function.
    The function 'func' is called per valid memory resouce range in [start,pfn).
    
    [EMAIL PROTECTED]: Error handling in walk_memory_resource()]
    Signed-off-by: KAMEZAWA Hiroyuki <[EMAIL PROTECTED]>
    Signed-off-by: Badari Pulavarty <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 include/linux/ioport.h         |    3 --
 include/linux/memory_hotplug.h |    8 +++++++
 kernel/resource.c              |   26 ++++++++++++++++++++++-
 mm/memory_hotplug.c            |   45 ++++++++++++++++-----------------------
 4 files changed, 52 insertions(+), 30 deletions(-)

diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 71ea923..6187a85 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -110,9 +110,6 @@ extern int allocate_resource(struct resource *root, struct 
resource *new,
 int adjust_resource(struct resource *res, resource_size_t start,
                    resource_size_t size);
 
-/* get registered SYSTEM_RAM resources in specified area */
-extern int find_next_system_ram(struct resource *res);
-
 /* Convenience shorthand with allocation */
 #define request_region(start,n,name)   __request_region(&ioport_resource, 
(start), (n), (name))
 #define request_mem_region(start,n,name) __request_region(&iomem_resource, 
(start), (n), (name))
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index b573d1e..0a14dad 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -63,6 +63,14 @@ extern int online_pages(unsigned long, unsigned long);
 extern int __add_pages(struct zone *zone, unsigned long start_pfn,
        unsigned long nr_pages);
 
+/*
+ * Walk thorugh all memory which is registered as resource.
+ * arg is (start_pfn, nr_pages, private_arg_pointer)
+ */
+extern int walk_memory_resource(unsigned long start_pfn,
+                       unsigned long nr_pages, void *arg,
+                       int (*func)(unsigned long, unsigned long, void *));
+
 #ifdef CONFIG_NUMA
 extern int memory_add_physaddr_to_nid(u64 start);
 #else
diff --git a/kernel/resource.c b/kernel/resource.c
index 9bd14fd..a358142 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -234,7 +234,7 @@ EXPORT_SYMBOL(release_resource);
  * the caller must specify res->start, res->end, res->flags.
  * If found, returns 0, res is overwritten, if not found, returns -1.
  */
-int find_next_system_ram(struct resource *res)
+static int find_next_system_ram(struct resource *res)
 {
        resource_size_t start, end;
        struct resource *p;
@@ -267,6 +267,30 @@ int find_next_system_ram(struct resource *res)
                res->end = p->end;
        return 0;
 }
+int
+walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void 
*arg,
+                       int (*func)(unsigned long, unsigned long, void *))
+{
+       struct resource res;
+       unsigned long pfn, len;
+       u64 orig_end;
+       int ret = -1;
+       res.start = (u64) start_pfn << PAGE_SHIFT;
+       res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1;
+       res.flags = IORESOURCE_MEM;
+       orig_end = res.end;
+       while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) {
+               pfn = (unsigned long)(res.start >> PAGE_SHIFT);
+               len = (unsigned long)((res.end + 1 - res.start) >> PAGE_SHIFT);
+               ret = (*func)(pfn, len, arg);
+               if (ret)
+                       break;
+               res.start = res.end + 1;
+               res.end = orig_end;
+       }
+       return ret;
+}
+
 #endif
 
 /*
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 9c12ae5..1cbe957 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -161,14 +161,27 @@ static void grow_pgdat_span(struct pglist_data *pgdat,
                                        pgdat->node_start_pfn;
 }
 
-int online_pages(unsigned long pfn, unsigned long nr_pages)
+static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
+                       void *arg)
 {
        unsigned long i;
+       unsigned long onlined_pages = *(unsigned long *)arg;
+       struct page *page;
+       if (PageReserved(pfn_to_page(start_pfn)))
+               for (i = 0; i < nr_pages; i++) {
+                       page = pfn_to_page(start_pfn + i);
+                       online_page(page);
+                       onlined_pages++;
+               }
+       *(unsigned long *)arg = onlined_pages;
+       return 0;
+}
+
+
+int online_pages(unsigned long pfn, unsigned long nr_pages)
+{
        unsigned long flags;
        unsigned long onlined_pages = 0;
-       struct resource res;
-       u64 section_end;
-       unsigned long start_pfn;
        struct zone *zone;
        int need_zonelists_rebuild = 0;
 
@@ -191,28 +204,8 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
        if (!populated_zone(zone))
                need_zonelists_rebuild = 1;
 
-       res.start = (u64)pfn << PAGE_SHIFT;
-       res.end = res.start + ((u64)nr_pages << PAGE_SHIFT) - 1;
-       res.flags = IORESOURCE_MEM; /* we just need system ram */
-       section_end = res.end;
-
-       while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) {
-               start_pfn = (unsigned long)(res.start >> PAGE_SHIFT);
-               nr_pages = (unsigned long)
-                           ((res.end + 1 - res.start) >> PAGE_SHIFT);
-
-               if (PageReserved(pfn_to_page(start_pfn))) {
-                       /* this region's page is not onlined now */
-                       for (i = 0; i < nr_pages; i++) {
-                               struct page *page = pfn_to_page(start_pfn + i);
-                               online_page(page);
-                               onlined_pages++;
-                       }
-               }
-
-               res.start = res.end + 1;
-               res.end = section_end;
-       }
+       walk_memory_resource(pfn, nr_pages, &onlined_pages,
+               online_pages_range);
        zone->present_pages += onlined_pages;
        zone->zone_pgdat->node_present_pages += onlined_pages;
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to