84 lines
2.6 KiB
Diff
84 lines
2.6 KiB
Diff
|
From: Peter Zijlstra <a.p.zijlstra@chello.nl>
|
||
|
Subject: [PATCH 07/31] mm: allow PF_MEMALLOC from softirq context
|
||
|
Patch-mainline: not yet
|
||
|
|
||
|
This is needed to allow network softirq packet processing to make use of
|
||
|
PF_MEMALLOC.
|
||
|
|
||
|
Currently softirq context cannot use PF_MEMALLOC due to it not being associated
|
||
|
with a task, and therefore not having task flags to fiddle with - thus the gfp
|
||
|
to alloc flag mapping ignores the task flags when in interrupts (hard or soft)
|
||
|
context.
|
||
|
|
||
|
Allowing softirqs to make use of PF_MEMALLOC therefore requires some trickery.
|
||
|
We basically borrow the task flags from whatever process happens to be
|
||
|
preempted by the softirq.
|
||
|
|
||
|
So we modify the gfp to alloc flags mapping to not exclude task flags in
|
||
|
softirq context, and modify the softirq code to save, clear and restore the
|
||
|
PF_MEMALLOC flag.
|
||
|
|
||
|
The save and clear, ensures the preempted task's PF_MEMALLOC flag doesn't
|
||
|
leak into the softirq. The restore ensures a softirq's PF_MEMALLOC flag cannot
|
||
|
leak back into the preempted process.
|
||
|
|
||
|
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
|
||
|
Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
|
||
|
---
|
||
|
include/linux/sched.h | 7 +++++++
|
||
|
kernel/softirq.c | 3 +++
|
||
|
mm/page_alloc.c | 7 ++++---
|
||
|
3 files changed, 14 insertions(+), 3 deletions(-)
|
||
|
|
||
|
--- a/include/linux/sched.h
|
||
|
+++ b/include/linux/sched.h
|
||
|
@@ -1772,6 +1772,13 @@ static inline void rcu_copy_process(stru
|
||
|
|
||
|
#endif
|
||
|
|
||
|
+static inline void tsk_restore_flags(struct task_struct *p,
|
||
|
+ unsigned long pflags, unsigned long mask)
|
||
|
+{
|
||
|
+ p->flags &= ~mask;
|
||
|
+ p->flags |= pflags & mask;
|
||
|
+}
|
||
|
+
|
||
|
#ifdef CONFIG_SMP
|
||
|
extern int set_cpus_allowed_ptr(struct task_struct *p,
|
||
|
const struct cpumask *new_mask);
|
||
|
--- a/kernel/softirq.c
|
||
|
+++ b/kernel/softirq.c
|
||
|
@@ -194,6 +194,8 @@ asmlinkage void __do_softirq(void)
|
||
|
__u32 pending;
|
||
|
int max_restart = MAX_SOFTIRQ_RESTART;
|
||
|
int cpu;
|
||
|
+ unsigned long pflags = current->flags;
|
||
|
+ current->flags &= ~PF_MEMALLOC;
|
||
|
|
||
|
pending = local_softirq_pending();
|
||
|
account_system_vtime(current);
|
||
|
@@ -246,6 +248,7 @@ restart:
|
||
|
|
||
|
account_system_vtime(current);
|
||
|
_local_bh_enable();
|
||
|
+ tsk_restore_flags(current, pflags, PF_MEMALLOC);
|
||
|
}
|
||
|
|
||
|
#ifndef __ARCH_HAS_DO_SOFTIRQ
|
||
|
--- a/mm/page_alloc.c
|
||
|
+++ b/mm/page_alloc.c
|
||
|
@@ -1785,9 +1785,10 @@ int gfp_to_alloc_flags(gfp_t gfp_mask)
|
||
|
alloc_flags |= ALLOC_HARDER;
|
||
|
|
||
|
if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) {
|
||
|
- if (!in_interrupt() &&
|
||
|
- ((p->flags & PF_MEMALLOC) ||
|
||
|
- unlikely(test_thread_flag(TIF_MEMDIE))))
|
||
|
+ if (!in_irq() && (p->flags & PF_MEMALLOC))
|
||
|
+ alloc_flags |= ALLOC_NO_WATERMARKS;
|
||
|
+ else if (!in_interrupt() &&
|
||
|
+ unlikely(test_thread_flag(TIF_MEMDIE)))
|
||
|
alloc_flags |= ALLOC_NO_WATERMARKS;
|
||
|
}
|
||
|
|