aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/page_alloc.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b2d21e06d45d..a8cfa9cc6e86 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1847,6 +1847,7 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
1847 struct page *page = NULL; 1847 struct page *page = NULL;
1848 struct reclaim_state reclaim_state; 1848 struct reclaim_state reclaim_state;
1849 struct task_struct *p = current; 1849 struct task_struct *p = current;
1850 bool drained = false;
1850 1851
1851 cond_resched(); 1852 cond_resched();
1852 1853
@@ -1865,14 +1866,25 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
1865 1866
1866 cond_resched(); 1867 cond_resched();
1867 1868
1868 if (order != 0) 1869 if (unlikely(!(*did_some_progress)))
1869 drain_all_pages(); 1870 return NULL;
1870 1871
1871 if (likely(*did_some_progress)) 1872retry:
1872 page = get_page_from_freelist(gfp_mask, nodemask, order, 1873 page = get_page_from_freelist(gfp_mask, nodemask, order,
1873 zonelist, high_zoneidx, 1874 zonelist, high_zoneidx,
1874 alloc_flags, preferred_zone, 1875 alloc_flags, preferred_zone,
1875 migratetype); 1876 migratetype);
1877
1878 /*
1879 * If an allocation failed after direct reclaim, it could be because
1880 * pages are pinned on the per-cpu lists. Drain them and try again
1881 */
1882 if (!page && !drained) {
1883 drain_all_pages();
1884 drained = true;
1885 goto retry;
1886 }
1887
1876 return page; 1888 return page;
1877} 1889}
1878 1890