|
@@ -20,9 +20,9 @@
|
|
|
static inline int gup_pte_range(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
|
|
|
unsigned long end, int write, struct page **pages, int *nr)
|
|
|
{
|
|
|
+ struct page *head, *page;
|
|
|
unsigned long mask;
|
|
|
pte_t *ptep, pte;
|
|
|
- struct page *page;
|
|
|
|
|
|
mask = (write ? _PAGE_PROTECT : 0) | _PAGE_INVALID | _PAGE_SPECIAL;
|
|
|
|
|
@@ -37,12 +37,14 @@ static inline int gup_pte_range(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
|
|
|
return 0;
|
|
|
VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
|
|
|
page = pte_page(pte);
|
|
|
- if (!page_cache_get_speculative(page))
|
|
|
+ head = compound_head(page);
|
|
|
+ if (!page_cache_get_speculative(head))
|
|
|
return 0;
|
|
|
if (unlikely(pte_val(pte) != pte_val(*ptep))) {
|
|
|
- put_page(page);
|
|
|
+ put_page(head);
|
|
|
return 0;
|
|
|
}
|
|
|
+ VM_BUG_ON_PAGE(compound_head(page) != head, page);
|
|
|
pages[*nr] = page;
|
|
|
(*nr)++;
|
|
|
|