diff options
Diffstat (limited to 'mm/rmap.c')
| -rw-r--r-- | mm/rmap.c | 19 | 
1 files changed, 10 insertions, 9 deletions
diff --git a/mm/rmap.c b/mm/rmap.c index fd3ee7a54a13..068522d8502a 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -600,8 +600,12 @@ pte_t *__page_check_address(struct page *page, struct mm_struct *mm,  	spinlock_t *ptl;  	if (unlikely(PageHuge(page))) { +		/* when pud is not present, pte will be NULL */  		pte = huge_pte_offset(mm, address); -		ptl = &mm->page_table_lock; +		if (!pte) +			return NULL; + +		ptl = huge_pte_lockptr(page_hstate(page), mm, pte);  		goto check;  	} @@ -665,25 +669,23 @@ int page_referenced_one(struct page *page, struct vm_area_struct *vma,  			unsigned long *vm_flags)  {  	struct mm_struct *mm = vma->vm_mm; +	spinlock_t *ptl;  	int referenced = 0;  	if (unlikely(PageTransHuge(page))) {  		pmd_t *pmd; -		spin_lock(&mm->page_table_lock);  		/*  		 * rmap might return false positives; we must filter  		 * these out using page_check_address_pmd().  		 */  		pmd = page_check_address_pmd(page, mm, address, -					     PAGE_CHECK_ADDRESS_PMD_FLAG); -		if (!pmd) { -			spin_unlock(&mm->page_table_lock); +					     PAGE_CHECK_ADDRESS_PMD_FLAG, &ptl); +		if (!pmd)  			goto out; -		}  		if (vma->vm_flags & VM_LOCKED) { -			spin_unlock(&mm->page_table_lock); +			spin_unlock(ptl);  			*mapcount = 0;	/* break early from loop */  			*vm_flags |= VM_LOCKED;  			goto out; @@ -692,10 +694,9 @@ int page_referenced_one(struct page *page, struct vm_area_struct *vma,  		/* go ahead even if the pmd is pmd_trans_splitting() */  		if (pmdp_clear_flush_young_notify(vma, address, pmd))  			referenced++; -		spin_unlock(&mm->page_table_lock); +		spin_unlock(ptl);  	} else {  		pte_t *pte; -		spinlock_t *ptl;  		/*  		 * rmap might return false positives; we must filter  | 
