mm/gup: allow to react to fatal signals
authorPeter Xu <peterx@redhat.com>
Thu, 2 Apr 2020 04:08:53 +0000 (21:08 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 Apr 2020 16:35:30 +0000 (09:35 -0700)
The existing gup code does not react to the fatal signals in many code
paths.  For example, in one retry path of gup we're still using
down_read() rather than down_read_killable().  Also, when doing page
faults we don't pass in FAULT_FLAG_KILLABLE as well, which means that
within the faulting process we'll wait in non-killable way as well.  These
were spotted by Linus during the code review of some other patches.

Let's allow the gup code to react to fatal signals to improve the
responsiveness of threads when during gup and being killed.

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/20200220160256.9887-1-peterx@redhat.com
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
mm/gup.c
mm/hugetlb.c

index efe9038933d969ba55e00b9c696e18c24d79fd21..da3e031851443aa1f2af714c3af93906b361cb67 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -864,7 +864,7 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma,
        if (*flags & FOLL_REMOTE)
                fault_flags |= FAULT_FLAG_REMOTE;
        if (locked)
-               fault_flags |= FAULT_FLAG_ALLOW_RETRY;
+               fault_flags |= FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
        if (*flags & FOLL_NOWAIT)
                fault_flags |= FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_RETRY_NOWAIT;
        if (*flags & FOLL_TRIED) {
@@ -1207,7 +1207,7 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
        address = untagged_addr(address);
 
        if (unlocked)
-               fault_flags |= FAULT_FLAG_ALLOW_RETRY;
+               fault_flags |= FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 retry:
        vma = find_extend_vma(mm, address);
@@ -1329,7 +1329,13 @@ retry:
                        break;
 
                *locked = 1;
-               down_read(&mm->mmap_sem);
+               ret = down_read_killable(&mm->mmap_sem);
+               if (ret) {
+                       BUG_ON(ret > 0);
+                       if (!pages_done)
+                               pages_done = ret;
+                       break;
+               }
 
                ret = __get_user_pages(tsk, mm, start, 1, flags | FOLL_TRIED,
                                       pages, NULL, locked);
index 0b15dc29e529807c4ad2aa8148042eb035b739a5..249c92917eb4099782be4d9d84b639cde1bf2887 100644 (file)
@@ -4344,7 +4344,8 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        if (flags & FOLL_WRITE)
                                fault_flags |= FAULT_FLAG_WRITE;
                        if (locked)
-                               fault_flags |= FAULT_FLAG_ALLOW_RETRY;
+                               fault_flags |= FAULT_FLAG_ALLOW_RETRY |
+                                       FAULT_FLAG_KILLABLE;
                        if (flags & FOLL_NOWAIT)
                                fault_flags |= FAULT_FLAG_ALLOW_RETRY |
                                        FAULT_FLAG_RETRY_NOWAIT;