mm: introduce fault_signal_pending()
authorPeter Xu <peterx@redhat.com>
Thu, 2 Apr 2020 04:08:06 +0000 (21:08 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 Apr 2020 16:35:29 +0000 (09:35 -0700)
For most architectures, we've got a quick path to detect fatal signal
after a handle_mm_fault().  Introduce a helper for that quick path.

It cleans the current codes a bit so we don't need to duplicate the same
check across archs.  More importantly, this will be an unified place that
we handle the signal immediately right after an interrupted page fault, so
it'll be much easier for us if we want to change the behavior of handling
signals later on for all the archs.

Note that currently only part of the archs are using this new helper,
because some archs have their own way to handle signals.  In the follow up
patches, we'll try to apply this helper to all the rest of archs.

Another note is that the "regs" parameter in the new helper is not used
yet.  It'll be used very soon.  Now we kept it in this patch only to avoid
touching all the archs again in the follow up patches.

[peterx@redhat.com: fix sparse warnings]
Link: http://lkml.kernel.org/r/20200311145921.GD479302@xz-x1
Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Tested-by: Brian Geffon <bgeffon@google.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Bobby Powers <bobbypowers@gmail.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: Denis Plotnikov <dplotnikov@virtuozzo.com>
Cc: "Dr . David Alan Gilbert" <dgilbert@redhat.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Jerome Glisse <jglisse@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: "Kirill A . Shutemov" <kirill@shutemov.name>
Cc: Martin Cracauer <cracauer@cons.org>
Cc: Marty McFadden <mcfadden8@llnl.gov>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Maya Gokhale <gokhale2@llnl.gov>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Mike Kravetz <mike.kravetz@oracle.com>
Cc: Mike Rapoport <rppt@linux.vnet.ibm.com>
Cc: Pavel Emelyanov <xemul@openvz.org>
Link: http://lkml.kernel.org/r/20200220155353.8676-4-peterx@redhat.com
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
18 files changed:
arch/alpha/mm/fault.c
arch/arm/mm/fault.c
arch/hexagon/mm/vm_fault.c
arch/ia64/mm/fault.c
arch/m68k/mm/fault.c
arch/microblaze/mm/fault.c
arch/mips/mm/fault.c
arch/nds32/mm/fault.c
arch/nios2/mm/fault.c
arch/openrisc/mm/fault.c
arch/parisc/mm/fault.c
arch/riscv/mm/fault.c
arch/s390/mm/fault.c
arch/sparc/mm/fault_32.c
arch/sparc/mm/fault_64.c
arch/unicore32/mm/fault.c
arch/xtensa/mm/fault.c
include/linux/sched/signal.h

index 741e61ef9d3fe4d11b8349f42fc0e404b60cb0fa..aea33b599037c24162ec9d5f688afa26b479b421 100644 (file)
@@ -150,7 +150,7 @@ retry:
           the fault.  */
        fault = handle_mm_fault(vma, address, flags);
 
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                return;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
index bd0f4821f7e11fa52b20e73fd1c0ea56bab728e6..937b81ff864992cc6f44e7924982fb16dbc93a42 100644 (file)
@@ -295,7 +295,7 @@ retry:
         * signal first. We do not need to release the mmap_sem because
         * it would already be released in __lock_page_or_retry in
         * mm/filemap.c. */
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) {
+       if (fault_signal_pending(fault, regs)) {
                if (!user_mode(regs))
                        goto no_context;
                return 0;
index b3bc71680ae448e0b5e7b7672740f51fefc603b1..d19beaf11b4cfad931a3de190213470616c77206 100644 (file)
@@ -91,7 +91,7 @@ good_area:
 
        fault = handle_mm_fault(vma, address, flags);
 
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                return;
 
        /* The most common case -- we are done. */
index c2f299fe9e04a88c8bc9675a5295141a4a0f82eb..211b4f43938464fd9a4e16a40312dbe8b401e990 100644 (file)
@@ -141,7 +141,7 @@ retry:
         */
        fault = handle_mm_fault(vma, address, flags);
 
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                return;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
index e9b1d7585b43bf5aaff5bead9ee2e9b537f0e800..a455e202691baff765e1ba1b9a06969b7b5cbd8f 100644 (file)
@@ -138,7 +138,7 @@ good_area:
        fault = handle_mm_fault(vma, address, flags);
        pr_debug("handle_mm_fault returns %x\n", fault);
 
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                return 0;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
index e6a810b0c7ad2086fd7387c6d1952962f6fcd758..cdde01dcdfc3c7004bd6f969c5e517110f302649 100644 (file)
@@ -217,7 +217,7 @@ good_area:
         */
        fault = handle_mm_fault(vma, address, flags);
 
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                return;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
index 1e8d007937844d1f52717d6e227cd9cebe496372..4b52f3d890ea90366c482c8583402ae9213467ed 100644 (file)
@@ -154,7 +154,7 @@ good_area:
         */
        fault = handle_mm_fault(vma, address, flags);
 
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                return;
 
        perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
index 906dfb25353cf123ffbc81c08ed2c8c5e2794c0a..0e63f81eff5bd5aaa20be6dc0a1b27dd23d68886 100644 (file)
@@ -214,7 +214,7 @@ good_area:
         * signal first. We do not need to release the mmap_sem because it
         * would already be released in __lock_page_or_retry in mm/filemap.c.
         */
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) {
+       if (fault_signal_pending(fault, regs)) {
                if (!user_mode(regs))
                        goto no_context;
                return;
index 6a2e716b959f7e9e8e962e5c901e0770bca22485..704ace8ca0eef45da12d018475ebb22034971635 100644 (file)
@@ -133,7 +133,7 @@ good_area:
         */
        fault = handle_mm_fault(vma, address, flags);
 
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                return;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
index 5d4d3a9691d0fb32d3bbcd8041e05bf4fa06c5f2..85c7eb0c01860cac71b19551a2c48096825b1d12 100644 (file)
@@ -161,7 +161,7 @@ good_area:
 
        fault = handle_mm_fault(vma, address, flags);
 
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                return;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
index adbd5e2144a34303023372e99b0452b0ce43bafa..f9be1d1cb43f6d9c692d21a0ac8a16457b59addd 100644 (file)
@@ -304,7 +304,7 @@ good_area:
 
        fault = handle_mm_fault(vma, address, flags);
 
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                return;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
index cf7248e07f439a13dfff4dcf2c69f689d3ac91d3..1d3869e9ddeff8a0fbcfbe3d0f59b4433895616d 100644 (file)
@@ -117,7 +117,7 @@ good_area:
         * signal first. We do not need to release the mmap_sem because it
         * would already be released in __lock_page_or_retry in mm/filemap.c.
         */
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(tsk))
+       if (fault_signal_pending(fault, regs))
                return;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
index 7b0bb475c166496ff054f18a780748a25c028a1c..179cf92a56e56277624bf417b28182641b002117 100644 (file)
@@ -480,8 +480,7 @@ retry:
         * the fault.
         */
        fault = handle_mm_fault(vma, address, flags);
-       /* No reason to continue if interrupted by SIGKILL. */
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) {
+       if (fault_signal_pending(fault, regs)) {
                fault = VM_FAULT_SIGNAL;
                if (flags & FAULT_FLAG_RETRY_NOWAIT)
                        goto out_up;
index 89976c9b936cfb242a06c80db5dcf9fc9fa96207..6efbeb22764411e08856ae79e8a6ef740d699cd1 100644 (file)
@@ -237,7 +237,7 @@ good_area:
         */
        fault = handle_mm_fault(vma, address, flags);
 
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                return;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
index 8b7ddbd14b658c4377bd8c61c5fc0c0abced38b2..dd1ed65558318b3088ba940aab4cd630a1f1e47b 100644 (file)
@@ -425,7 +425,7 @@ good_area:
 
        fault = handle_mm_fault(vma, address, flags);
 
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                goto exit_exception;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
index 76342de9cf8cbe026748cb06ce8c66440e6c4d6b..59d0e6ec2cfca6fdb8ddc0519855679328ca02e8 100644 (file)
@@ -250,7 +250,7 @@ retry:
         * signal first. We do not need to release the mmap_sem because
         * it would already be released in __lock_page_or_retry in
         * mm/filemap.c. */
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                return 0;
 
        if (!(fault & VM_FAULT_ERROR) && (flags & FAULT_FLAG_ALLOW_RETRY)) {
index bee30a77cd700d030273328ea7a6ba5df9f24959..59515905d4ad39a72470d7a1d40164ff189b8f65 100644 (file)
@@ -110,7 +110,7 @@ good_area:
         */
        fault = handle_mm_fault(vma, address, flags);
 
-       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+       if (fault_signal_pending(fault, regs))
                return;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
index 88050259c466e1feebd1dcb1ab4ac2ffdf58efa6..7e7271374799112978cb32191e744441db4e3436 100644 (file)
@@ -10,6 +10,8 @@
 #include <linux/cred.h>
 #include <linux/refcount.h>
 #include <linux/posix-timers.h>
+#include <linux/mm_types.h>
+#include <asm/ptrace.h>
 
 /*
  * Types defining task->signal and task->sighand and APIs using them:
@@ -369,6 +371,19 @@ static inline int signal_pending_state(long state, struct task_struct *p)
        return (state & TASK_INTERRUPTIBLE) || __fatal_signal_pending(p);
 }
 
+/*
+ * This should only be used in fault handlers to decide whether we
+ * should stop the current fault routine to handle the signals
+ * instead, especially with the case where we've got interrupted with
+ * a VM_FAULT_RETRY.
+ */
+static inline bool fault_signal_pending(vm_fault_t fault_flags,
+                                       struct pt_regs *regs)
+{
+       return unlikely((fault_flags & VM_FAULT_RETRY) &&
+                       fatal_signal_pending(current));
+}
+
 /*
  * Reevaluate whether the task has signals pending delivery.
  * Wake the task if so.