diff options
| author | Vladimir Davydov <vdavydov@virtuozzo.com> | 2016-01-15 16:54:45 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-15 17:56:32 -0800 | 
| commit | 8749cfea11f3fffe8f7cad891470a77b36e0185f (patch) | |
| tree | 1dc712f15e259ba4ff9c0ec62134440b28e89666 /mm/page_idle.c | |
| parent | d965432234db94ee8e185f8fd8e3181bed7459fd (diff) | |
mm: add page_check_address_transhuge() helper
page_referenced_one() and page_idle_clear_pte_refs_one() duplicate the
code for looking up pte of a (possibly transhuge) page.  Move this code
to a new helper function, page_check_address_transhuge(), and make the
above mentioned functions use it.
This is just a cleanup, no functional changes are intended.
Signed-off-by: Vladimir Davydov <vdavydov@virtuozzo.com>
Reviewed-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_idle.c')
| -rw-r--r-- | mm/page_idle.c | 63 | 
1 files changed, 9 insertions, 54 deletions
| diff --git a/mm/page_idle.c b/mm/page_idle.c index 2c553ba969f8..4ea9c4ef5146 100644 --- a/mm/page_idle.c +++ b/mm/page_idle.c @@ -55,71 +55,26 @@ static int page_idle_clear_pte_refs_one(struct page *page,  					unsigned long addr, void *arg)  {  	struct mm_struct *mm = vma->vm_mm; -	spinlock_t *ptl; -	pgd_t *pgd; -	pud_t *pud;  	pmd_t *pmd;  	pte_t *pte; +	spinlock_t *ptl;  	bool referenced = false; -	pgd = pgd_offset(mm, addr); -	if (!pgd_present(*pgd)) -		return SWAP_AGAIN; -	pud = pud_offset(pgd, addr); -	if (!pud_present(*pud)) +	if (!page_check_address_transhuge(page, mm, addr, &pmd, &pte, &ptl))  		return SWAP_AGAIN; -	pmd = pmd_offset(pud, addr); - -	if (pmd_trans_huge(*pmd)) { -		ptl = pmd_lock(mm, pmd); -		if (!pmd_present(*pmd)) -			goto unlock_pmd; -		if (unlikely(!pmd_trans_huge(*pmd))) { -			spin_unlock(ptl); -			goto map_pte; -		} - -		if (pmd_page(*pmd) != page) -			goto unlock_pmd; +	if (pte) { +		referenced = ptep_clear_young_notify(vma, addr, pte); +		pte_unmap(pte); +	} else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {  		referenced = pmdp_clear_young_notify(vma, addr, pmd); -		spin_unlock(ptl); -		goto found; -unlock_pmd: -		spin_unlock(ptl); -		return SWAP_AGAIN;  	} else { -		pmd_t pmde = *pmd; - -		barrier(); -		if (!pmd_present(pmde) || pmd_trans_huge(pmde)) -			return SWAP_AGAIN; - -	} -map_pte: -	pte = pte_offset_map(pmd, addr); -	if (!pte_present(*pte)) { -		pte_unmap(pte); -		return SWAP_AGAIN; +		/* unexpected pmd-mapped page? */ +		WARN_ON_ONCE(1);  	} -	ptl = pte_lockptr(mm, pmd); -	spin_lock(ptl); - -	if (!pte_present(*pte)) { -		pte_unmap_unlock(pte, ptl); -		return SWAP_AGAIN; -	} - -	/* THP can be referenced by any subpage */ -	if (pte_pfn(*pte) - page_to_pfn(page) >= hpage_nr_pages(page)) { -		pte_unmap_unlock(pte, ptl); -		return SWAP_AGAIN; -	} +	spin_unlock(ptl); -	referenced = ptep_clear_young_notify(vma, addr, pte); -	pte_unmap_unlock(pte, ptl); -found:  	if (referenced) {  		clear_page_idle(page);  		/* | 
