diff options
-rw-r--r-- | include/linux/sched.h | 22 | ||||
-rw-r--r-- | mm/page_alloc.c | 9 | ||||
-rw-r--r-- | mm/vmscan.c | 4 |
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 */ | ||
1834 | static 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 | |||
1841 | static 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 | |||
1848 | static 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 | }; |