Commit 1501899a authored by Dan Williams's avatar Dan Williams Committed by Linus Torvalds
Browse files

mm: fix device-dax pud write-faults triggered by get_user_pages()

Currently only get_user_pages_fast() can safely handle the writable gup
case due to its use of pud_access_permitted() to check whether the pud
entry is writable.  In the gup slow path pud_write() is used instead of
pud_access_permitted() and to date it has been unimplemented, just calls

    kernel BUG at ./include/linux/hugetlb.h:244!
    RIP: 0010:follow_devmap_pud+0x482/0x490
    Call Trace:
     ? nfs_start_io_direct+0x63/0x70

For now this just implements a simple check for the _PAGE_RW bit similar
to pmd_write.  However, this implies that the gup-slow-path check is
missing the extra checks that the gup-fast-path performs with
pud_access_permitted.  Later patches will align all checks to use the
'access_permitted' helper if the architecture provides it.

Note that the generic 'access_permitted' helper fallback is the simple
_PAGE_RW check on architectures that do not define the
'access_permitted' helper(s).

[ fix powerpc compile error]
Fixes: a00cc7d9

 ("mm, x86: add support for PUD-sized transparent hugepages")
Signed-off-by: default avatarDan Williams <>
Reported-by: default avatarStephen Rothwell <>
Acked-by: Thomas Gleixner <>	[x86]
Cc: Kirill A. Shutemov <>
Cc: Catalin Marinas <>
Cc: "David S. Miller" <>
Cc: Dave Hansen <>
Cc: Will Deacon <>
Cc: "H. Peter Anvin" <>
Cc: Ingo Molnar <>
Cc: Arnd Bergmann <>
Cc: <>
Signed-off-by: default avatarAndrew Morton <>
Signed-off-by: default avatarLinus Torvalds <>
parent 63cd4489
......@@ -1088,6 +1088,12 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
clear_bit(_PAGE_BIT_RW, (unsigned long *)pmdp);
#define pud_write pud_write
static inline int pud_write(pud_t pud)
return pud_flags(pud) & _PAGE_RW;
* clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
......@@ -814,6 +814,14 @@ static inline int pmd_write(pmd_t pmd)
#endif /* __HAVE_ARCH_PMD_WRITE */
#ifndef pud_write
static inline int pud_write(pud_t pud)
return 0;
#endif /* pud_write */
......@@ -239,14 +239,6 @@ static inline int pgd_write(pgd_t pgd)
#ifndef pud_write
static inline int pud_write(pud_t pud)
return 0;
#define HUGETLB_ANON_FILE "anon_hugepage"
enum {
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment