diff options
Diffstat (limited to 'mm/mempolicy.c')
| -rw-r--r-- | mm/mempolicy.c | 15 | 
1 files changed, 14 insertions, 1 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index edc25195f5bd..c53f8beeb507 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -384,8 +384,10 @@ void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new)  	VMA_ITERATOR(vmi, mm, 0);  	mmap_write_lock(mm); -	for_each_vma(vmi, vma) +	for_each_vma(vmi, vma) { +		vma_start_write(vma);  		mpol_rebind_policy(vma->vm_policy, new); +	}  	mmap_write_unlock(mm);  } @@ -768,6 +770,8 @@ static int vma_replace_policy(struct vm_area_struct *vma,  	struct mempolicy *old;  	struct mempolicy *new; +	vma_assert_write_locked(vma); +  	pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",  		 vma->vm_start, vma->vm_end, vma->vm_pgoff,  		 vma->vm_ops, vma->vm_file, @@ -1313,6 +1317,14 @@ static long do_mbind(unsigned long start, unsigned long len,  	if (err)  		goto mpol_out; +	/* +	 * Lock the VMAs before scanning for pages to migrate, to ensure we don't +	 * miss a concurrently inserted page. +	 */ +	vma_iter_init(&vmi, mm, start); +	for_each_vma_range(vmi, vma, end) +		vma_start_write(vma); +  	ret = queue_pages_range(mm, start, end, nmask,  			  flags | MPOL_MF_INVERT, &pagelist); @@ -1538,6 +1550,7 @@ SYSCALL_DEFINE4(set_mempolicy_home_node, unsigned long, start, unsigned long, le  			break;  		} +		vma_start_write(vma);  		new->home_node = home_node;  		err = mbind_range(&vmi, vma, &prev, start, end, new);  		mpol_put(new);  |