]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - mm/page_alloc.c
checkpatch: improve --git <commit-count> shortcut
[karo-tx-linux.git] / mm / page_alloc.c
index 38ad6dd7cba0141188273efd13797bfcdb9586f2..f8f3bfc435eec5bf0144798f6b890e6deacee0f6 100644 (file)
@@ -522,12 +522,6 @@ static void bad_page(struct page *page, const char *reason,
        static unsigned long nr_shown;
        static unsigned long nr_unshown;
 
-       /* Don't complain about poisoned pages */
-       if (PageHWPoison(page)) {
-               page_mapcount_reset(page); /* remove PageBuddy */
-               return;
-       }
-
        /*
         * Allow a burst of 60 reports, then keep quiet for that minute;
         * or allow a steady drip of one report per second.
@@ -613,14 +607,7 @@ static int __init early_debug_pagealloc(char *buf)
 {
        if (!buf)
                return -EINVAL;
-
-       if (strcmp(buf, "on") == 0)
-               _debug_pagealloc_enabled = true;
-
-       if (strcmp(buf, "off") == 0)
-               _debug_pagealloc_enabled = false;
-
-       return 0;
+       return kstrtobool(buf, &_debug_pagealloc_enabled);
 }
 early_param("debug_pagealloc", early_debug_pagealloc);
 
@@ -1000,7 +987,6 @@ static __always_inline bool free_pages_prepare(struct page *page,
 
        trace_mm_page_free(page, order);
        kmemcheck_free_shadow(page, order);
-       kasan_free_pages(page, order);
 
        /*
         * Check tail pages before head page information is cleared to
@@ -1042,6 +1028,7 @@ static __always_inline bool free_pages_prepare(struct page *page,
        arch_free_page(page, order);
        kernel_poison_pages(page, 1 << order, 0);
        kernel_map_pages(page, 1 << order, 0);
+       kasan_free_pages(page, order);
 
        return true;
 }
@@ -1212,7 +1199,7 @@ static inline void init_reserved_page(unsigned long pfn)
  * marks the pages PageReserved. The remaining valid pages are later
  * sent to the buddy page allocator.
  */
-void __meminit reserve_bootmem_region(unsigned long start, unsigned long end)
+void __meminit reserve_bootmem_region(phys_addr_t start, phys_addr_t end)
 {
        unsigned long start_pfn = PFN_DOWN(start);
        unsigned long end_pfn = PFN_UP(end);
@@ -1661,6 +1648,9 @@ static void check_new_page_bad(struct page *page)
        if (unlikely(page->flags & __PG_HWPOISON)) {
                bad_reason = "HWPoisoned (hardware-corrupted)";
                bad_flags = __PG_HWPOISON;
+               /* Don't complain about hwpoisoned pages */
+               page_mapcount_reset(page); /* remove PageBuddy */
+               return;
        }
        if (unlikely(page->flags & PAGE_FLAGS_CHECK_AT_PREP)) {
                bad_reason = "PAGE_FLAGS_CHECK_AT_PREP flag set";
@@ -2750,10 +2740,9 @@ static inline bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
  * one free page of a suitable size. Checking now avoids taking the zone lock
  * to check in the allocation paths if no pages are free.
  */
-static bool __zone_watermark_ok(struct zone *z, unsigned int order,
-                       unsigned long mark, int classzone_idx,
-                       unsigned int alloc_flags,
-                       long free_pages)
+bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,
+                        int classzone_idx, unsigned int alloc_flags,
+                        long free_pages)
 {
        long min = mark;
        int o;
@@ -3256,10 +3245,12 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
 }
 
 static inline bool
-should_compact_retry(unsigned int order, enum compact_result compact_result,
-                    enum migrate_mode *migrate_mode,
+should_compact_retry(struct alloc_context *ac, int order, int alloc_flags,
+                    enum compact_result compact_result, enum migrate_mode *migrate_mode,
                     int compaction_retries)
 {
+       int max_retries = MAX_COMPACT_RETRIES;
+
        if (!order)
                return false;
 
@@ -3277,17 +3268,26 @@ should_compact_retry(unsigned int order, enum compact_result compact_result,
        }
 
        /*
-        * !costly allocations are really important and we have to make sure
-        * the compaction wasn't deferred or didn't bail out early due to locks
-        * contention before we go OOM. Still cap the reclaim retry loops with
-        * progress to prevent from looping forever and potential trashing.
+        * make sure the compaction wasn't deferred or didn't bail out early
+        * due to locks contention before we declare that we should give up.
+        * But do not retry if the given zonelist is not suitable for
+        * compaction.
         */
-       if (order <= PAGE_ALLOC_COSTLY_ORDER) {
-               if (compaction_withdrawn(compact_result))
-                       return true;
-               if (compaction_retries <= MAX_COMPACT_RETRIES)
-                       return true;
-       }
+       if (compaction_withdrawn(compact_result))
+               return compaction_zonelist_suitable(ac, order, alloc_flags);
+
+       /*
+        * !costly requests are much more important than __GFP_REPEAT
+        * costly ones because they are de facto nofail and invoke OOM
+        * killer to move on while costly can fail and users are ready
+        * to cope with that. 1/4 retries is rather arbitrary but we
+        * would need much more detailed feedback from compaction to
+        * make a better decision.
+        */
+       if (order > PAGE_ALLOC_COSTLY_ORDER)
+               max_retries /= 4;
+       if (compaction_retries <= max_retries)
+               return true;
 
        return false;
 }
@@ -3302,10 +3302,29 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
 }
 
 static inline bool
-should_compact_retry(unsigned int order, enum compact_result compact_result,
+should_compact_retry(struct alloc_context *ac, unsigned int order, int alloc_flags,
+                    enum compact_result compact_result,
                     enum migrate_mode *migrate_mode,
                     int compaction_retries)
 {
+       struct zone *zone;
+       struct zoneref *z;
+
+       if (!order || order > PAGE_ALLOC_COSTLY_ORDER)
+               return false;
+
+       /*
+        * There are setups with compaction disabled which would prefer to loop
+        * inside the allocator rather than hit the oom killer prematurely.
+        * Let's give them a good hope and keep retrying while the order-0
+        * watermarks are OK.
+        */
+       for_each_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx,
+                                       ac->nodemask) {
+               if (zone_watermark_ok(zone, 0, min_wmark_pages(zone),
+                                       ac_classzone_idx(ac), alloc_flags))
+                       return true;
+       }
        return false;
 }
 #endif /* CONFIG_COMPACTION */
@@ -3449,18 +3468,17 @@ static inline bool is_thp_gfp_mask(gfp_t gfp_mask)
  * Checks whether it makes sense to retry the reclaim to make a forward progress
  * for the given allocation request.
  * The reclaim feedback represented by did_some_progress (any progress during
- * the last reclaim round), pages_reclaimed (cumulative number of reclaimed
- * pages) and no_progress_loops (number of reclaim rounds without any progress
- * in a row) is considered as well as the reclaimable pages on the applicable
- * zone list (with a backoff mechanism which is a function of no_progress_loops).
+ * the last reclaim round) and no_progress_loops (number of reclaim rounds without
+ * any progress in a row) is considered as well as the reclaimable pages on the
+ * applicable zone list (with a backoff mechanism which is a function of
+ * no_progress_loops).
  *
  * Returns true if a retry is viable or false to enter the oom path.
  */
 static inline bool
 should_reclaim_retry(gfp_t gfp_mask, unsigned order,
                     struct alloc_context *ac, int alloc_flags,
-                    bool did_some_progress, unsigned long pages_reclaimed,
-                    int no_progress_loops)
+                    bool did_some_progress, int no_progress_loops)
 {
        struct zone *zone;
        struct zoneref *z;
@@ -3472,14 +3490,6 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order,
        if (no_progress_loops > MAX_RECLAIM_RETRIES)
                return false;
 
-       if (order > PAGE_ALLOC_COSTLY_ORDER) {
-               if (pages_reclaimed >= (1<<order))
-                       return false;
-
-               if (did_some_progress)
-                       return true;
-       }
-
        /*
         * Keep reclaiming pages while there is a chance this will lead somewhere.
         * If none of the target zones can satisfy our allocation request even
@@ -3550,7 +3560,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
        bool can_direct_reclaim = gfp_mask & __GFP_DIRECT_RECLAIM;
        struct page *page = NULL;
        unsigned int alloc_flags;
-       unsigned long pages_reclaimed = 0;
        unsigned long did_some_progress;
        enum migrate_mode migration_mode = MIGRATE_ASYNC;
        enum compact_result compact_result;
@@ -3686,16 +3695,18 @@ retry:
        if (order > PAGE_ALLOC_COSTLY_ORDER && !(gfp_mask & __GFP_REPEAT))
                goto noretry;
 
-       if (did_some_progress) {
+       /*
+        * Costly allocations might have made a progress but this doesn't mean
+        * their order will become available due to high fragmentation so
+        * always increment the no progress counter for them
+        */
+       if (did_some_progress && order <= PAGE_ALLOC_COSTLY_ORDER)
                no_progress_loops = 0;
-               pages_reclaimed += did_some_progress;
-       } else {
+       else
                no_progress_loops++;
-       }
 
        if (should_reclaim_retry(gfp_mask, order, ac, alloc_flags,
-                                did_some_progress > 0, pages_reclaimed,
-                                no_progress_loops))
+                                did_some_progress > 0, no_progress_loops))
                goto retry;
 
        /*
@@ -3705,8 +3716,9 @@ retry:
         * of free memory (see __compaction_suitable)
         */
        if (did_some_progress > 0 &&
-                       should_compact_retry(order, compact_result,
-                               &migration_mode, compaction_retries))
+                       should_compact_retry(ac, order, alloc_flags,
+                               compact_result, &migration_mode,
+                               compaction_retries))
                goto retry;
 
        /* Reclaim has failed us, start killing things */