|
@@ -127,6 +127,13 @@ void pm_restrict_gfp_mask(void)
|
|
|
saved_gfp_mask = gfp_allowed_mask;
|
|
|
gfp_allowed_mask &= ~GFP_IOFS;
|
|
|
}
|
|
|
+
|
|
|
+bool pm_suspended_storage(void)
|
|
|
+{
|
|
|
+ if ((gfp_allowed_mask & GFP_IOFS) == GFP_IOFS)
|
|
|
+ return false;
|
|
|
+ return true;
|
|
|
+}
|
|
|
#endif /* CONFIG_PM_SLEEP */
|
|
|
|
|
|
#ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
|
|
@@ -1786,12 +1793,25 @@ void warn_alloc_failed(gfp_t gfp_mask, int order, const char *fmt, ...)
|
|
|
|
|
|
static inline int
|
|
|
should_alloc_retry(gfp_t gfp_mask, unsigned int order,
|
|
|
+ unsigned long did_some_progress,
|
|
|
unsigned long pages_reclaimed)
|
|
|
{
|
|
|
/* Do not loop if specifically requested */
|
|
|
if (gfp_mask & __GFP_NORETRY)
|
|
|
return 0;
|
|
|
|
|
|
+ /* Always retry if specifically requested */
|
|
|
+ if (gfp_mask & __GFP_NOFAIL)
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Suspend converts GFP_KERNEL to __GFP_WAIT which can prevent reclaim
|
|
|
+ * making forward progress without invoking OOM. Suspend also disables
|
|
|
+ * storage devices so kswapd will not help. Bail if we are suspending.
|
|
|
+ */
|
|
|
+ if (!did_some_progress && pm_suspended_storage())
|
|
|
+ return 0;
|
|
|
+
|
|
|
/*
|
|
|
* In this implementation, order <= PAGE_ALLOC_COSTLY_ORDER
|
|
|
* means __GFP_NOFAIL, but that may not be true in other
|
|
@@ -1810,13 +1830,6 @@ should_alloc_retry(gfp_t gfp_mask, unsigned int order,
|
|
|
if (gfp_mask & __GFP_REPEAT && pages_reclaimed < (1 << order))
|
|
|
return 1;
|
|
|
|
|
|
- /*
|
|
|
- * Don't let big-order allocations loop unless the caller
|
|
|
- * explicitly requests that.
|
|
|
- */
|
|
|
- if (gfp_mask & __GFP_NOFAIL)
|
|
|
- return 1;
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -2209,7 +2222,8 @@ rebalance:
|
|
|
|
|
|
/* Check if we should retry the allocation */
|
|
|
pages_reclaimed += did_some_progress;
|
|
|
- if (should_alloc_retry(gfp_mask, order, pages_reclaimed)) {
|
|
|
+ if (should_alloc_retry(gfp_mask, order, did_some_progress,
|
|
|
+ pages_reclaimed)) {
|
|
|
/* Wait for some write requests to complete then retry */
|
|
|
wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/50);
|
|
|
goto rebalance;
|