Skip to content

Commit 1c0fe6e

Browse files
Nick Piggintorvalds
authored andcommitted
mm: invoke oom-killer from page fault
Rather than have the pagefault handler kill a process directly if it gets a VM_FAULT_OOM, have it call into the OOM killer. With increasingly sophisticated oom behaviour (cpusets, memory cgroups, oom killing throttling, oom priority adjustment or selective disabling, panic on oom, etc), it's silly to unconditionally kill the faulting process at page fault time. Create a hook for pagefault oom path to call into instead. Only converted x86 and uml so far. [[email protected]: make __out_of_memory() static] [[email protected]: fix comment] Signed-off-by: Nick Piggin <[email protected]> Cc: Jeff Dike <[email protected]> Acked-by: Ingo Molnar <[email protected]> Cc: Thomas Gleixner <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 5bd1455 commit 1c0fe6e

File tree

4 files changed

+84
-63
lines changed

4 files changed

+84
-63
lines changed

arch/um/kernel/trap.c

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,10 @@ int handle_page_fault(unsigned long address, unsigned long ip,
6464

6565
do {
6666
int fault;
67-
survive:
67+
6868
fault = handle_mm_fault(mm, vma, address, is_write);
6969
if (unlikely(fault & VM_FAULT_ERROR)) {
7070
if (fault & VM_FAULT_OOM) {
71-
err = -ENOMEM;
7271
goto out_of_memory;
7372
} else if (fault & VM_FAULT_SIGBUS) {
7473
err = -EACCES;
@@ -104,18 +103,14 @@ int handle_page_fault(unsigned long address, unsigned long ip,
104103
out_nosemaphore:
105104
return err;
106105

107-
/*
108-
* We ran out of memory, or some other thing happened to us that made
109-
* us unable to handle the page fault gracefully.
110-
*/
111106
out_of_memory:
112-
if (is_global_init(current)) {
113-
up_read(&mm->mmap_sem);
114-
yield();
115-
down_read(&mm->mmap_sem);
116-
goto survive;
117-
}
118-
goto out;
107+
/*
108+
* We ran out of memory, call the OOM killer, and return the userspace
109+
* (which will retry the fault, or kill us if we got oom-killed).
110+
*/
111+
up_read(&mm->mmap_sem);
112+
pagefault_out_of_memory();
113+
return 0;
119114
}
120115

121116
static void bad_segv(struct faultinfo fi, unsigned long ip)
@@ -214,9 +209,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
214209
si.si_addr = (void __user *)address;
215210
current->thread.arch.faultinfo = fi;
216211
force_sig_info(SIGBUS, &si, current);
217-
} else if (err == -ENOMEM) {
218-
printk(KERN_INFO "VM: killing process %s\n", current->comm);
219-
do_exit(SIGKILL);
220212
} else {
221213
BUG_ON(err != -EFAULT);
222214
si.si_signo = SIGSEGV;

arch/x86/mm/fault.c

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,6 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
667667
if (unlikely(in_atomic() || !mm))
668668
goto bad_area_nosemaphore;
669669

670-
again:
671670
/*
672671
* When running in the kernel we expect faults to occur only to
673672
* addresses in user space. All other faults represent errors in the
@@ -859,25 +858,14 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
859858
oops_end(flags, regs, sig);
860859
#endif
861860

862-
/*
863-
* We ran out of memory, or some other thing happened to us that made
864-
* us unable to handle the page fault gracefully.
865-
*/
866861
out_of_memory:
862+
/*
863+
* We ran out of memory, call the OOM killer, and return the userspace
864+
* (which will retry the fault, or kill us if we got oom-killed).
865+
*/
867866
up_read(&mm->mmap_sem);
868-
if (is_global_init(tsk)) {
869-
yield();
870-
/*
871-
* Re-lookup the vma - in theory the vma tree might
872-
* have changed:
873-
*/
874-
goto again;
875-
}
876-
877-
printk("VM: killing process %s\n", tsk->comm);
878-
if (error_code & PF_USER)
879-
do_group_exit(SIGKILL);
880-
goto no_context;
867+
pagefault_out_of_memory();
868+
return;
881869

882870
do_sigbus:
883871
up_read(&mm->mmap_sem);

include/linux/mm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,11 @@ static inline int page_mapped(struct page *page)
717717

718718
#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS)
719719

720+
/*
721+
* Can be called by the pagefault handler when it gets a VM_FAULT_OOM.
722+
*/
723+
extern void pagefault_out_of_memory(void);
724+
720725
#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
721726

722727
extern void show_free_areas(void);

mm/oom_kill.c

Lines changed: 65 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,69 @@ void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_mask)
509509
spin_unlock(&zone_scan_mutex);
510510
}
511511

512+
/*
513+
* Must be called with tasklist_lock held for read.
514+
*/
515+
static void __out_of_memory(gfp_t gfp_mask, int order)
516+
{
517+
if (sysctl_oom_kill_allocating_task) {
518+
oom_kill_process(current, gfp_mask, order, 0, NULL,
519+
"Out of memory (oom_kill_allocating_task)");
520+
521+
} else {
522+
unsigned long points;
523+
struct task_struct *p;
524+
525+
retry:
526+
/*
527+
* Rambo mode: Shoot down a process and hope it solves whatever
528+
* issues we may have.
529+
*/
530+
p = select_bad_process(&points, NULL);
531+
532+
if (PTR_ERR(p) == -1UL)
533+
return;
534+
535+
/* Found nothing?!?! Either we hang forever, or we panic. */
536+
if (!p) {
537+
read_unlock(&tasklist_lock);
538+
panic("Out of memory and no killable processes...\n");
539+
}
540+
541+
if (oom_kill_process(p, gfp_mask, order, points, NULL,
542+
"Out of memory"))
543+
goto retry;
544+
}
545+
}
546+
547+
/*
548+
* pagefault handler calls into here because it is out of memory but
549+
* doesn't know exactly how or why.
550+
*/
551+
void pagefault_out_of_memory(void)
552+
{
553+
unsigned long freed = 0;
554+
555+
blocking_notifier_call_chain(&oom_notify_list, 0, &freed);
556+
if (freed > 0)
557+
/* Got some memory back in the last second. */
558+
return;
559+
560+
if (sysctl_panic_on_oom)
561+
panic("out of memory from page fault. panic_on_oom is selected.\n");
562+
563+
read_lock(&tasklist_lock);
564+
__out_of_memory(0, 0); /* unknown gfp_mask and order */
565+
read_unlock(&tasklist_lock);
566+
567+
/*
568+
* Give "p" a good chance of killing itself before we
569+
* retry to allocate memory.
570+
*/
571+
if (!test_thread_flag(TIF_MEMDIE))
572+
schedule_timeout_uninterruptible(1);
573+
}
574+
512575
/**
513576
* out_of_memory - kill the "best" process when we run out of memory
514577
* @zonelist: zonelist pointer
@@ -522,8 +585,6 @@ void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_mask)
522585
*/
523586
void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
524587
{
525-
struct task_struct *p;
526-
unsigned long points = 0;
527588
unsigned long freed = 0;
528589
enum oom_constraint constraint;
529590

@@ -544,7 +605,7 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
544605

545606
switch (constraint) {
546607
case CONSTRAINT_MEMORY_POLICY:
547-
oom_kill_process(current, gfp_mask, order, points, NULL,
608+
oom_kill_process(current, gfp_mask, order, 0, NULL,
548609
"No available memory (MPOL_BIND)");
549610
break;
550611

@@ -553,35 +614,10 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
553614
panic("out of memory. panic_on_oom is selected\n");
554615
/* Fall-through */
555616
case CONSTRAINT_CPUSET:
556-
if (sysctl_oom_kill_allocating_task) {
557-
oom_kill_process(current, gfp_mask, order, points, NULL,
558-
"Out of memory (oom_kill_allocating_task)");
559-
break;
560-
}
561-
retry:
562-
/*
563-
* Rambo mode: Shoot down a process and hope it solves whatever
564-
* issues we may have.
565-
*/
566-
p = select_bad_process(&points, NULL);
567-
568-
if (PTR_ERR(p) == -1UL)
569-
goto out;
570-
571-
/* Found nothing?!?! Either we hang forever, or we panic. */
572-
if (!p) {
573-
read_unlock(&tasklist_lock);
574-
panic("Out of memory and no killable processes...\n");
575-
}
576-
577-
if (oom_kill_process(p, gfp_mask, order, points, NULL,
578-
"Out of memory"))
579-
goto retry;
580-
617+
__out_of_memory(gfp_mask, order);
581618
break;
582619
}
583620

584-
out:
585621
read_unlock(&tasklist_lock);
586622

587623
/*

0 commit comments

Comments
 (0)