aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sched.h22
-rw-r--r--mm/page_alloc.c9
-rw-r--r--mm/vmscan.c4
3 files changed, 32 insertions, 3 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index e4112aad2964..c2182b53dace 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -51,6 +51,7 @@ struct sched_param {
51#include <linux/cred.h> 51#include <linux/cred.h>
52#include <linux/llist.h> 52#include <linux/llist.h>
53#include <linux/uidgid.h> 53#include <linux/uidgid.h>
54#include <linux/gfp.h>
54 55
55#include <asm/processor.h> 56#include <asm/processor.h>
56 57
@@ -1791,6 +1792,7 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut,
1791#define PF_FROZEN 0x00010000 /* frozen for system suspend */ 1792#define PF_FROZEN 0x00010000 /* frozen for system suspend */
1792#define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */ 1793#define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */
1793#define PF_KSWAPD 0x00040000 /* I am kswapd */ 1794#define PF_KSWAPD 0x00040000 /* I am kswapd */
1795#define PF_MEMALLOC_NOIO 0x00080000 /* Allocating memory without IO involved */
1794#define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */ 1796#define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */
1795#define PF_KTHREAD 0x00200000 /* I am a kernel thread */ 1797#define PF_KTHREAD 0x00200000 /* I am a kernel thread */
1796#define PF_RANDOMIZE 0x00400000 /* randomize virtual address space */ 1798#define PF_RANDOMIZE 0x00400000 /* randomize virtual address space */
@@ -1828,6 +1830,26 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut,
1828#define tsk_used_math(p) ((p)->flags & PF_USED_MATH) 1830#define tsk_used_math(p) ((p)->flags & PF_USED_MATH)
1829#define used_math() tsk_used_math(current) 1831#define used_math() tsk_used_math(current)
1830 1832
1833/* __GFP_IO isn't allowed if PF_MEMALLOC_NOIO is set in current->flags */
1834static inline gfp_t memalloc_noio_flags(gfp_t flags)
1835{
1836 if (unlikely(current->flags & PF_MEMALLOC_NOIO))
1837 flags &= ~__GFP_IO;
1838 return flags;
1839}
1840
1841static inline unsigned int memalloc_noio_save(void)
1842{
1843 unsigned int flags = current->flags & PF_MEMALLOC_NOIO;
1844 current->flags |= PF_MEMALLOC_NOIO;
1845 return flags;
1846}
1847
1848static inline void memalloc_noio_restore(unsigned int flags)
1849{
1850 current->flags = (current->flags & ~PF_MEMALLOC_NOIO) | flags;
1851}
1852
1831/* 1853/*
1832 * task->jobctl flags 1854 * task->jobctl flags
1833 */ 1855 */
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index e3fb290194c0..3ede25e6686e 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2624,10 +2624,17 @@ retry_cpuset:
2624 page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order, 2624 page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order,
2625 zonelist, high_zoneidx, alloc_flags, 2625 zonelist, high_zoneidx, alloc_flags,
2626 preferred_zone, migratetype); 2626 preferred_zone, migratetype);
2627 if (unlikely(!page)) 2627 if (unlikely(!page)) {
2628 /*
2629 * Runtime PM, block IO and its error handling path
2630 * can deadlock because I/O on the device might not
2631 * complete.
2632 */
2633 gfp_mask = memalloc_noio_flags(gfp_mask);
2628 page = __alloc_pages_slowpath(gfp_mask, order, 2634 page = __alloc_pages_slowpath(gfp_mask, order,
2629 zonelist, high_zoneidx, nodemask, 2635 zonelist, high_zoneidx, nodemask,
2630 preferred_zone, migratetype); 2636 preferred_zone, migratetype);
2637 }
2631 2638
2632 trace_mm_page_alloc(page, order, gfp_mask, migratetype); 2639 trace_mm_page_alloc(page, order, gfp_mask, migratetype);
2633 2640
diff --git a/mm/vmscan.c b/mm/vmscan.c
index b93968b71dc6..a68fa20269d9 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2352,7 +2352,7 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
2352{ 2352{
2353 unsigned long nr_reclaimed; 2353 unsigned long nr_reclaimed;
2354 struct scan_control sc = { 2354 struct scan_control sc = {
2355 .gfp_mask = gfp_mask, 2355 .gfp_mask = (gfp_mask = memalloc_noio_flags(gfp_mask)),
2356 .may_writepage = !laptop_mode, 2356 .may_writepage = !laptop_mode,
2357 .nr_to_reclaim = SWAP_CLUSTER_MAX, 2357 .nr_to_reclaim = SWAP_CLUSTER_MAX,
2358 .may_unmap = 1, 2358 .may_unmap = 1,
@@ -3313,7 +3313,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
3313 .may_unmap = !!(zone_reclaim_mode & RECLAIM_SWAP), 3313 .may_unmap = !!(zone_reclaim_mode & RECLAIM_SWAP),
3314 .may_swap = 1, 3314 .may_swap = 1,
3315 .nr_to_reclaim = max(nr_pages, SWAP_CLUSTER_MAX), 3315 .nr_to_reclaim = max(nr_pages, SWAP_CLUSTER_MAX),
3316 .gfp_mask = gfp_mask, 3316 .gfp_mask = (gfp_mask = memalloc_noio_flags(gfp_mask)),
3317 .order = order, 3317 .order = order,
3318 .priority = ZONE_RECLAIM_PRIORITY, 3318 .priority = ZONE_RECLAIM_PRIORITY,
3319 }; 3319 };