diff options
Diffstat (limited to 'arch/x86/mm/gup.c')
| -rw-r--r-- | arch/x86/mm/gup.c | 21 | 
1 files changed, 17 insertions, 4 deletions
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c index dd74e46828c..207d9aef662 100644 --- a/arch/x86/mm/gup.c +++ b/arch/x86/mm/gup.c @@ -83,6 +83,12 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,  		pte_t pte = gup_get_pte(ptep);  		struct page *page; +		/* Similar to the PMD case, NUMA hinting must take slow path */ +		if (pte_numa(pte)) { +			pte_unmap(ptep); +			return 0; +		} +  		if ((pte_flags(pte) & (mask | _PAGE_SPECIAL)) != mask) {  			pte_unmap(ptep);  			return 0; @@ -102,8 +108,8 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,  static inline void get_head_page_multiple(struct page *page, int nr)  { -	VM_BUG_ON(page != compound_head(page)); -	VM_BUG_ON(page_count(page) == 0); +	VM_BUG_ON_PAGE(page != compound_head(page), page); +	VM_BUG_ON_PAGE(page_count(page) == 0, page);  	atomic_add(nr, &page->_count);  	SetPageReferenced(page);  } @@ -129,7 +135,7 @@ static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr,  	head = pte_page(pte);  	page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);  	do { -		VM_BUG_ON(compound_head(page) != head); +		VM_BUG_ON_PAGE(compound_head(page) != head, page);  		pages[*nr] = page;  		if (PageTail(page))  			get_huge_page_tail(page); @@ -167,6 +173,13 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,  		if (pmd_none(pmd) || pmd_trans_splitting(pmd))  			return 0;  		if (unlikely(pmd_large(pmd))) { +			/* +			 * NUMA hinting faults need to be handled in the GUP +			 * slowpath for accounting purposes and so that they +			 * can be serialised against THP migration. +			 */ +			if (pmd_numa(pmd)) +				return 0;  			if (!gup_huge_pmd(pmd, addr, next, write, pages, nr))  				return 0;  		} else { @@ -199,7 +212,7 @@ static noinline int gup_huge_pud(pud_t pud, unsigned long addr,  	head = pte_page(pte);  	page = head + ((addr & ~PUD_MASK) >> PAGE_SHIFT);  	do { -		VM_BUG_ON(compound_head(page) != head); +		VM_BUG_ON_PAGE(compound_head(page) != head, page);  		pages[*nr] = page;  		if (PageTail(page))  			get_huge_page_tail(page);  | 
