|
|
@@ -3260,6 +3260,8 @@ should_compact_retry(unsigned int order, 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 +3279,24 @@ 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.
|
|
|
*/
|
|
|
- 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 true;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * !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;
|
|
|
}
|
|
|
@@ -3449,18 +3458,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 +3480,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 +3550,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 +3685,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;
|
|
|
|
|
|
/*
|