commit d2a1ce44cd81b8ccf426a6c40a3a0d9b2b51e076 Author: Robert Stupp Date: Wed Nov 6 12:58:12 2019 +0100 make mlockall(MCL_CURRENT) aware of new VM_FAULT_RETRY conditions mlockall(MCL_CURRENT) can run into an busy/endless loop in __mm_populate(). This can happen since 6b4c9f4469819a0c1a38a0a4541337e0f9bf6c11 (introduced in Linux 5.1), "filemap: drop the mmap_sem for all blocking operations" / new VM_FAULT_RETRY conditions. The fix here is to replace the call to __get_user_pages() with a call to __get_user_pages_locked() in populate_vma_page_range(). This change seems to fix the behavior for mlockall(MCL_CURRENT) but does not change the behavior for other usages of populate_vma_page_range() in find_extend_vma() and mprotect_fixup(). (Text by Johannes Weiner hannes-at-cmpxchg.org): The only way this can occur is if populate_vma_page_range() returns 0 and we don't advance the iteration position (if it returned an error, we wouldn't reset nend and move on to the next vma as ignore_errors is 1 for mlockall.) populate_vma_page_range() returns 0 when the first page is not found and faultin_page() returns -EBUSY (if it were processing pages, or if the error from faultin_page() would be a different one, we would return the number of pages processed or -error). faultin_page() returns -EBUSY when VM_FAULT_RETRY is set, i.e. we dropped the mmap_sem in order to initiate IO and require a retry. That is consistent with the bisect result (new VM_FAULT_RETRY conditions). At this point, regular page fault would retry with FAULT_FLAG_TRIED to indicate that the mmap_sem cannot be dropped a second time. diff --git a/mm/gup.c b/mm/gup.c index 98f13ab37bac..e319ffb625b1 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1227,8 +1227,8 @@ long populate_vma_page_range(struct vm_area_struct *vma, * We made sure addr is within a VMA, so the following will * not result in a stack expansion that recurses back here. */ - return __get_user_pages(current, mm, start, nr_pages, gup_flags, - NULL, NULL, nonblocking); + return __get_user_pages_locked(current, mm, start, nr_pages, + NULL, NULL, nonblocking, gup_flags); } /*