aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>2011-05-24 20:11:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-25 11:39:08 -0400
commit37b23e0525d393d48a7d59f870b3bc061a30ccdb (patch)
tree467e6fcd785108a21d836e1aad8fc1a68aa72e17
parentf62e00cc3a00bfbd394a79fc22b334c31f91bd5f (diff)
x86,mm: make pagefault killable
When an oom killing occurs, almost all processes are getting stuck at the following two points. 1) __alloc_pages_nodemask 2) __lock_page_or_retry 1) is not very problematic because TIF_MEMDIE leads to an allocation failure and getting out from page allocator. 2) is more problematic. In an OOM situation, zones typically don't have page cache at all and memory starvation might lead to greatly reduced IO performance. When a fork bomb occurs, TIF_MEMDIE tasks don't die quickly, meaning that a fork bomb may create new process quickly rather than the oom-killer killing it. Then, the system may become livelocked. This patch makes the pagefault interruptible by SIGKILL. Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Minchan Kim <minchan.kim@gmail.com> Cc: Matthew Wilcox <willy@linux.intel.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: "H. Peter Anvin" <hpa@zytor.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/x86/mm/fault.c12
-rw-r--r--include/linux/mm.h1
-rw-r--r--mm/filemap.c31
3 files changed, 36 insertions, 8 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index bcb394dfbb35..f7a2a054a3c0 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -965,7 +965,7 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code)
965 struct mm_struct *mm; 965 struct mm_struct *mm;
966 int fault; 966 int fault;
967 int write = error_code & PF_WRITE; 967 int write = error_code & PF_WRITE;
968 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | 968 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
969 (write ? FAULT_FLAG_WRITE : 0); 969 (write ? FAULT_FLAG_WRITE : 0);
970 970
971 tsk = current; 971 tsk = current;
@@ -1139,6 +1139,16 @@ good_area:
1139 } 1139 }
1140 1140
1141 /* 1141 /*
1142 * Pagefault was interrupted by SIGKILL. We have no reason to
1143 * continue pagefault.
1144 */
1145 if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) {
1146 if (!(error_code & PF_USER))
1147 no_context(regs, error_code, address);
1148 return;
1149 }
1150
1151 /*
1142 * Major/minor page fault accounting is only done on the 1152 * Major/minor page fault accounting is only done on the
1143 * initial attempt. If we go through a retry, it is extremely 1153 * initial attempt. If we go through a retry, it is extremely
1144 * likely that the page will be found in page cache at that point. 1154 * likely that the page will be found in page cache at that point.
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 1746f67c33de..57d3d5fade16 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -153,6 +153,7 @@ extern pgprot_t protection_map[16];
153#define FAULT_FLAG_MKWRITE 0x04 /* Fault was mkwrite of existing pte */ 153#define FAULT_FLAG_MKWRITE 0x04 /* Fault was mkwrite of existing pte */
154#define FAULT_FLAG_ALLOW_RETRY 0x08 /* Retry fault if blocking */ 154#define FAULT_FLAG_ALLOW_RETRY 0x08 /* Retry fault if blocking */
155#define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */ 155#define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */
156#define FAULT_FLAG_KILLABLE 0x20 /* The fault task is in SIGKILL killable region */
156 157
157/* 158/*
158 * This interface is used by x86 PAT code to identify a pfn mapping that is 159 * This interface is used by x86 PAT code to identify a pfn mapping that is
diff --git a/mm/filemap.c b/mm/filemap.c
index dea8a38bb2bb..8144f87dcbb4 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -654,15 +654,32 @@ EXPORT_SYMBOL_GPL(__lock_page_killable);
654int __lock_page_or_retry(struct page *page, struct mm_struct *mm, 654int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
655 unsigned int flags) 655 unsigned int flags)
656{ 656{
657 if (!(flags & FAULT_FLAG_ALLOW_RETRY)) { 657 if (flags & FAULT_FLAG_ALLOW_RETRY) {
658 __lock_page(page); 658 /*
659 return 1; 659 * CAUTION! In this case, mmap_sem is not released
660 } else { 660 * even though return 0.
661 if (!(flags & FAULT_FLAG_RETRY_NOWAIT)) { 661 */
662 up_read(&mm->mmap_sem); 662 if (flags & FAULT_FLAG_RETRY_NOWAIT)
663 return 0;
664
665 up_read(&mm->mmap_sem);
666 if (flags & FAULT_FLAG_KILLABLE)
667 wait_on_page_locked_killable(page);
668 else
663 wait_on_page_locked(page); 669 wait_on_page_locked(page);
664 }
665 return 0; 670 return 0;
671 } else {
672 if (flags & FAULT_FLAG_KILLABLE) {
673 int ret;
674
675 ret = __lock_page_killable(page);
676 if (ret) {
677 up_read(&mm->mmap_sem);
678 return 0;
679 }
680 } else
681 __lock_page(page);
682 return 1;
666 } 683 }
667} 684}
668 685