]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - mm/page_alloc.c
Merge tag 'gfs2-for-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2
[linux.git] / mm / page_alloc.c
index d047bf7d8fd406b9959969ab65b433d8954b2803..15e908ad933bc281bf0753158459387df1867fd3 100644 (file)
@@ -5848,6 +5848,30 @@ overlap_memmap_init(unsigned long zone, unsigned long *pfn)
        return false;
 }
 
+#ifdef CONFIG_SPARSEMEM
+/* Skip PFNs that belong to non-present sections */
+static inline __meminit unsigned long next_pfn(unsigned long pfn)
+{
+       unsigned long section_nr;
+
+       section_nr = pfn_to_section_nr(++pfn);
+       if (present_section_nr(section_nr))
+               return pfn;
+
+       while (++section_nr <= __highest_present_section_nr) {
+               if (present_section_nr(section_nr))
+                       return section_nr_to_pfn(section_nr);
+       }
+
+       return -1;
+}
+#else
+static inline __meminit unsigned long next_pfn(unsigned long pfn)
+{
+       return pfn++;
+}
+#endif
+
 /*
  * Initially all pages are reserved - free ones are freed
  * up by memblock_free_all() once the early boot process is
@@ -5887,8 +5911,10 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
                 * function.  They do not exist on hotplugged memory.
                 */
                if (context == MEMMAP_EARLY) {
-                       if (!early_pfn_valid(pfn))
+                       if (!early_pfn_valid(pfn)) {
+                               pfn = next_pfn(pfn) - 1;
                                continue;
+                       }
                        if (!early_pfn_in_nid(pfn, nid))
                                continue;
                        if (overlap_memmap_init(zone, &pfn))
@@ -8154,20 +8180,22 @@ void *__init alloc_large_system_hash(const char *tablename,
 
 /*
  * This function checks whether pageblock includes unmovable pages or not.
- * If @count is not zero, it is okay to include less @count unmovable pages
  *
  * PageLRU check without isolation or lru_lock could race so that
  * MIGRATE_MOVABLE block might include unmovable pages. And __PageMovable
  * check without lock_page also may miss some movable non-lru pages at
  * race condition. So you can't expect this function should be exact.
+ *
+ * Returns a page without holding a reference. If the caller wants to
+ * dereference that page (e.g., dumping), it has to make sure that that it
+ * cannot get removed (e.g., via memory unplug) concurrently.
+ *
  */
-bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
-                        int migratetype, int flags)
+struct page *has_unmovable_pages(struct zone *zone, struct page *page,
+                                int migratetype, int flags)
 {
-       unsigned long found;
        unsigned long iter = 0;
        unsigned long pfn = page_to_pfn(page);
-       const char *reason = "unmovable page";
 
        /*
         * TODO we could make this much more efficient by not checking every
@@ -8184,22 +8212,19 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
                 * so consider them movable here.
                 */
                if (is_migrate_cma(migratetype))
-                       return false;
+                       return NULL;
 
-               reason = "CMA page";
-               goto unmovable;
+               return page;
        }
 
-       for (found = 0; iter < pageblock_nr_pages; iter++) {
-               unsigned long check = pfn + iter;
-
-               if (!pfn_valid_within(check))
+       for (; iter < pageblock_nr_pages; iter++) {
+               if (!pfn_valid_within(pfn + iter))
                        continue;
 
-               page = pfn_to_page(check);
+               page = pfn_to_page(pfn + iter);
 
                if (PageReserved(page))
-                       goto unmovable;
+                       return page;
 
                /*
                 * If the zone is movable and we have ruled out all reserved
@@ -8219,7 +8244,7 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
                        unsigned int skip_pages;
 
                        if (!hugepage_migration_supported(page_hstate(head)))
-                               goto unmovable;
+                               return page;
 
                        skip_pages = compound_nr(head) - (page - head);
                        iter += skip_pages - 1;
@@ -8245,11 +8270,9 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
                if ((flags & MEMORY_OFFLINE) && PageHWPoison(page))
                        continue;
 
-               if (__PageMovable(page))
+               if (__PageMovable(page) || PageLRU(page))
                        continue;
 
-               if (!PageLRU(page))
-                       found++;
                /*
                 * If there are RECLAIMABLE pages, we need to check
                 * it.  But now, memory offline itself doesn't call
@@ -8263,15 +8286,9 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
                 * is set to both of a memory hole page and a _used_ kernel
                 * page at boot.
                 */
-               if (found > count)
-                       goto unmovable;
+               return page;
        }
-       return false;
-unmovable:
-       WARN_ON_ONCE(zone_idx(zone) == ZONE_MOVABLE);
-       if (flags & REPORT_FAILURE)
-               dump_page(pfn_to_page(pfn + iter), reason);
-       return true;
+       return NULL;
 }
 
 #ifdef CONFIG_CONTIG_ALLOC
@@ -8675,10 +8692,6 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
                BUG_ON(!PageBuddy(page));
                order = page_order(page);
                offlined_pages += 1 << order;
-#ifdef CONFIG_DEBUG_VM
-               pr_info("remove from free list %lx %d %lx\n",
-                       pfn, 1 << order, end_pfn);
-#endif
                del_page_from_free_area(page, &zone->free_area[order]);
                pfn += (1 << order);
        }