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 741e61e..aea33b5 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 bd0f482..937b81f 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 b3bc716..d19beaf 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 c2f299f..211b4f4 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 e9b1d75..a455e20 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 e6a810b..cdde01d 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 1e8d007..4b52f3d 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 906dfb2..0e63f81 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 6a2e716..704ace8 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 5d4d3a9..85c7eb0 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 adbd5e2..f9be1d1 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 cf7248e..1d3869e 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 7b0bb47..179cf92 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 89976c9..6efbeb2 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 8b7ddbd..dd1ed65 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 76342de..59d0e6e 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 bee30a7..5951590 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 8805025..7e72713 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.