diff options
-rw-r--r-- | include/linux/sched.h | 7 | ||||
-rw-r--r-- | kernel/softirq.c | 9 | ||||
-rw-r--r-- | mm/page_alloc.c | 6 |
3 files changed, 21 insertions, 1 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index 865725adb9d3..c147e7024f11 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1894,6 +1894,13 @@ static inline void rcu_copy_process(struct task_struct *p) | |||
1894 | 1894 | ||
1895 | #endif | 1895 | #endif |
1896 | 1896 | ||
1897 | static inline void tsk_restore_flags(struct task_struct *task, | ||
1898 | unsigned long orig_flags, unsigned long flags) | ||
1899 | { | ||
1900 | task->flags &= ~flags; | ||
1901 | task->flags |= orig_flags & flags; | ||
1902 | } | ||
1903 | |||
1897 | #ifdef CONFIG_SMP | 1904 | #ifdef CONFIG_SMP |
1898 | extern void do_set_cpus_allowed(struct task_struct *p, | 1905 | extern void do_set_cpus_allowed(struct task_struct *p, |
1899 | const struct cpumask *new_mask); | 1906 | const struct cpumask *new_mask); |
diff --git a/kernel/softirq.c b/kernel/softirq.c index 671f9594e368..b73e681df09e 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -210,6 +210,14 @@ asmlinkage void __do_softirq(void) | |||
210 | __u32 pending; | 210 | __u32 pending; |
211 | int max_restart = MAX_SOFTIRQ_RESTART; | 211 | int max_restart = MAX_SOFTIRQ_RESTART; |
212 | int cpu; | 212 | int cpu; |
213 | unsigned long old_flags = current->flags; | ||
214 | |||
215 | /* | ||
216 | * Mask out PF_MEMALLOC s current task context is borrowed for the | ||
217 | * softirq. A softirq handled such as network RX might set PF_MEMALLOC | ||
218 | * again if the socket is related to swap | ||
219 | */ | ||
220 | current->flags &= ~PF_MEMALLOC; | ||
213 | 221 | ||
214 | pending = local_softirq_pending(); | 222 | pending = local_softirq_pending(); |
215 | account_system_vtime(current); | 223 | account_system_vtime(current); |
@@ -265,6 +273,7 @@ restart: | |||
265 | 273 | ||
266 | account_system_vtime(current); | 274 | account_system_vtime(current); |
267 | __local_bh_enable(SOFTIRQ_OFFSET); | 275 | __local_bh_enable(SOFTIRQ_OFFSET); |
276 | tsk_restore_flags(current, old_flags, PF_MEMALLOC); | ||
268 | } | 277 | } |
269 | 278 | ||
270 | #ifndef __ARCH_HAS_DO_SOFTIRQ | 279 | #ifndef __ARCH_HAS_DO_SOFTIRQ |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 8f65abeb9ad6..cd5390f2f18d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -2296,7 +2296,11 @@ gfp_to_alloc_flags(gfp_t gfp_mask) | |||
2296 | if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) { | 2296 | if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) { |
2297 | if (gfp_mask & __GFP_MEMALLOC) | 2297 | if (gfp_mask & __GFP_MEMALLOC) |
2298 | alloc_flags |= ALLOC_NO_WATERMARKS; | 2298 | alloc_flags |= ALLOC_NO_WATERMARKS; |
2299 | else if (likely(!(gfp_mask & __GFP_NOMEMALLOC)) && !in_interrupt()) | 2299 | else if (in_serving_softirq() && (current->flags & PF_MEMALLOC)) |
2300 | alloc_flags |= ALLOC_NO_WATERMARKS; | ||
2301 | else if (!in_interrupt() && | ||
2302 | ((current->flags & PF_MEMALLOC) || | ||
2303 | unlikely(test_thread_flag(TIF_MEMDIE)))) | ||
2300 | alloc_flags |= ALLOC_NO_WATERMARKS; | 2304 | alloc_flags |= ALLOC_NO_WATERMARKS; |
2301 | } | 2305 | } |
2302 | 2306 | ||