diff options
Diffstat (limited to 'mm/rmap.c')
| -rw-r--r-- | mm/rmap.c | 39 | 
1 files changed, 22 insertions, 17 deletions
| diff --git a/mm/rmap.c b/mm/rmap.c index 795f9d5f8386..b9eb5c12f3fe 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -1440,21 +1440,20 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,  		/*  		 * If the page is mlock()d, we cannot swap it out.  		 */ -		if (!(flags & TTU_IGNORE_MLOCK)) { -			if (vma->vm_flags & VM_LOCKED) { -				/* PTE-mapped THP are never marked as mlocked */ -				if (!PageTransCompound(page) || -				    (PageHead(page) && !PageDoubleMap(page))) { -					/* -					 * Holding pte lock, we do *not* need -					 * mmap_lock here -					 */ -					mlock_vma_page(page); -				} -				ret = false; -				page_vma_mapped_walk_done(&pvmw); -				break; -			} +		if (!(flags & TTU_IGNORE_MLOCK) && +		    (vma->vm_flags & VM_LOCKED)) { +			/* +			 * PTE-mapped THP are never marked as mlocked: so do +			 * not set it on a DoubleMap THP, nor on an Anon THP +			 * (which may still be PTE-mapped after DoubleMap was +			 * cleared).  But stop unmapping even in those cases. +			 */ +			if (!PageTransCompound(page) || (PageHead(page) && +			     !PageDoubleMap(page) && !PageAnon(page))) +				mlock_vma_page(page); +			page_vma_mapped_walk_done(&pvmw); +			ret = false; +			break;  		}  		/* Unexpected PMD-mapped THP? */ @@ -1986,8 +1985,10 @@ static bool page_mlock_one(struct page *page, struct vm_area_struct *vma,  		 */  		if (vma->vm_flags & VM_LOCKED) {  			/* -			 * PTE-mapped THP are never marked as mlocked, but -			 * this function is never called when PageDoubleMap(). +			 * PTE-mapped THP are never marked as mlocked; but +			 * this function is never called on a DoubleMap THP, +			 * nor on an Anon THP (which may still be PTE-mapped +			 * after DoubleMap was cleared).  			 */  			mlock_vma_page(page);  			/* @@ -2022,6 +2023,10 @@ void page_mlock(struct page *page)  	VM_BUG_ON_PAGE(!PageLocked(page) || PageLRU(page), page);  	VM_BUG_ON_PAGE(PageCompound(page) && PageDoubleMap(page), page); +	/* Anon THP are only marked as mlocked when singly mapped */ +	if (PageTransCompound(page) && PageAnon(page)) +		return; +  	rmap_walk(page, &rwc);  } |