Patch "mm/hugetlb: report -EHWPOISON not -EFAULT when FOLL_HWPOISON is specified" has been added to the 4.11-stable tree
Subsystems (5)
This is a note to let you know that I've just added the patch titled
mm/hugetlb: report -EHWPOISON not -EFAULT when FOLL_HWPOISON is specified
to the 4.11-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
mm-hugetlb-report-ehwpoison-not-efault-when-foll_hwpoison-is-specified.patch
and it can be found in the queue-4.11 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
9a291a7c9428155e8e623e4a3989f8be47134df5Mon Sep 17 00:00:00 2001
From: James Morse <[email protected]>
Date: Fri, 2 Jun 2017 14:46:46 -0700
Subject: mm/hugetlb: report -EHWPOISON not -EFAULT when FOLL_HWPOISON is specified
From: James Morse <[email protected]>
commit 9a291a7c9428155e8e623e4a3989f8be47134df5 upstream.
KVM uses get_user_pages() to resolve its stage2 faults. KVM sets the FOLL_HWPOISON flag causing faultin_page() to return -EHWPOISON when it finds a VM_FAULT_HWPOISON. KVM handles these hwpoison pages as a special case. (check_user_page_hwpoison())
When huge pages are involved, this doesn't work so well. get_user_pages() calls follow_hugetlb_page(), which stops early if it receives VM_FAULT_HWPOISON from hugetlb_fault(), eventually returning -EFAULT to the caller. The step to map this to -EHWPOISON based on the FOLL_ flags is missing. The hwpoison special case is skipped, and -EFAULT is returned to user-space, causing Qemu or kvmtool to exit.
Instead, move this VM_FAULT_ to errno mapping code into a header file and use it from faultin_page() and follow_hugetlb_page().
With this, KVM works as expected.
This isn't a problem for arm64 today as we haven't enabled MEMORY_FAILURE, but I can't see any reason this doesn't happen on x86 too, so I think this should be a fix. This doesn't apply earlier than stable's v4.11.1 due to all sorts of cleanup.
[[email protected]: add vm_fault_to_errno() call to faultin_page()] suggested.
--- include/linux/mm.h | 11 +++++++++++ mm/gup.c | 20 ++++++++------------ mm/hugetlb.c | 5 +++++ 3 files changed, 24 insertions(+), 12 deletions(-)
include/linux/mm.h +11 -0
@@ -2315,6 +2315,17 @@ static inline struct page *follow_page(s#define FOLL_REMOTE 0x2000/* we are working on non-current tsk/mm */ #define FOLL_COW 0x4000/* internal GUP flag */ +static inline int vm_fault_to_errno (int vm_fault,int foll_flags) +{ +if (vm_fault &VM_FAULT_OOM ) +return -ENOMEM ; +if (vm_fault & (VM_FAULT_HWPOISON |VM_FAULT_HWPOISON_LARGE )) +return (foll_flags &FOLL_HWPOISON ) ? -EHWPOISON : -EFAULT ; +if (vm_fault & (VM_FAULT_SIGBUS |VM_FAULT_SIGSEGV )) +return -EFAULT ; +return 0 ; +} +typedef int (*pte_fn_t )(pte_t *pte,pgtable_t token,unsigned long addr,void *data); extern int apply_to_page_range(struct mm_struct *mm, unsigned long address,
mm/gup.c +8 -12
@@ -407,12 +407,10 @@ static int faultin_page(struct task_stru ret =handle_mm_fault (vma, address, fault_flags);if (ret &VM_FAULT_ERROR ) { -if (ret &VM_FAULT_OOM ) -return -ENOMEM ; -if (ret & (VM_FAULT_HWPOISON |VM_FAULT_HWPOISON_LARGE )) -return *flags &FOLL_HWPOISON ? -EHWPOISON : -EFAULT ; -if (ret & (VM_FAULT_SIGBUS |VM_FAULT_SIGSEGV )) -return -EFAULT ; +int err =vm_fault_to_errno (ret, *flags); + +if (err) +return err;BUG (); }
@@ -723,12 +721,10 @@ retry: ret =handle_mm_fault (vma, address, fault_flags); major |= ret &VM_FAULT_MAJOR ;if (ret &VM_FAULT_ERROR ) { -if (ret &VM_FAULT_OOM ) -return -ENOMEM ; -if (ret & (VM_FAULT_HWPOISON |VM_FAULT_HWPOISON_LARGE )) -return -EHWPOISON ; -if (ret & (VM_FAULT_SIGBUS |VM_FAULT_SIGSEGV )) -return -EFAULT ; +int err =vm_fault_to_errno (ret,0 ); + +if (err) +return err;BUG (); }
mm/hugetlb.c +5 -0
@@ -4170,6 +4170,11 @@ long follow_hugetlb_page(struct mm_struc } ret =hugetlb_fault (mm, vma, vaddr, fault_flags);if (ret &VM_FAULT_ERROR ) { +int err =vm_fault_to_errno (ret, flags); + +if (err) +return err; + remainder =0 ;break ; }
Patches currently in stable-queue which might be from [email protected] are
queue-4.11/mm-hugetlb-report-ehwpoison-not-efault-when-foll_hwpoison-is-specified.patch