diff options
Diffstat (limited to 'mm/memory.c')
| -rw-r--r-- | mm/memory.c | 16 | 
1 files changed, 9 insertions, 7 deletions
diff --git a/mm/memory.c b/mm/memory.c index c8e357627318..5efa07fb6cdc 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -809,12 +809,8 @@ copy_present_page(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma  		  pte_t *dst_pte, pte_t *src_pte, unsigned long addr, int *rss,  		  struct page **prealloc, pte_t pte, struct page *page)  { -	struct mm_struct *src_mm = src_vma->vm_mm;  	struct page *new_page; -	if (!is_cow_mapping(src_vma->vm_flags)) -		return 1; -  	/*  	 * What we want to do is to check whether this page may  	 * have been pinned by the parent process.  If so, @@ -828,9 +824,7 @@ copy_present_page(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma  	 * the page count. That might give false positives for  	 * for pinning, but it will work correctly.  	 */ -	if (likely(!atomic_read(&src_mm->has_pinned))) -		return 1; -	if (likely(!page_maybe_dma_pinned(page))) +	if (likely(!page_needs_cow_for_dma(src_vma, page)))  		return 1;  	new_page = *prealloc; @@ -3103,6 +3097,14 @@ static vm_fault_t do_wp_page(struct vm_fault *vmf)  		return handle_userfault(vmf, VM_UFFD_WP);  	} +	/* +	 * Userfaultfd write-protect can defer flushes. Ensure the TLB +	 * is flushed in this case before copying. +	 */ +	if (unlikely(userfaultfd_wp(vmf->vma) && +		     mm_tlb_flush_pending(vmf->vma->vm_mm))) +		flush_tlb_page(vmf->vma, vmf->address); +  	vmf->page = vm_normal_page(vma, vmf->address, vmf->orig_pte);  	if (!vmf->page) {  		/*  | 
