mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	untangling do_mremap(), part 1
Take locating vma and checks on it to a separate helper (it will be shared between MREMAP_FIXED/non-MREMAP_FIXED cases when we split them in the next patch) Acked-by: Russell King <rmk+kernel@arm.linux.org.uk> Acked-by: Hugh Dickins <hugh.dickins@tiscali.co.uk> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									3ef884b4c0
								
							
						
					
					
						commit
						54f5de7099
					
				
					 1 changed files with 55 additions and 33 deletions
				
			
		
							
								
								
									
										88
									
								
								mm/mremap.c
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								mm/mremap.c
									
									
									
									
									
								
							| 
						 | 
					@ -261,6 +261,58 @@ static unsigned long move_vma(struct vm_area_struct *vma,
 | 
				
			||||||
	return new_addr;
 | 
						return new_addr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct vm_area_struct *vma_to_resize(unsigned long addr,
 | 
				
			||||||
 | 
						unsigned long old_len, unsigned long new_len, unsigned long *p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mm_struct *mm = current->mm;
 | 
				
			||||||
 | 
						struct vm_area_struct *vma = find_vma(mm, addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!vma || vma->vm_start > addr)
 | 
				
			||||||
 | 
							goto Efault;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (is_vm_hugetlb_page(vma))
 | 
				
			||||||
 | 
							goto Einval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* We can't remap across vm area boundaries */
 | 
				
			||||||
 | 
						if (old_len > vma->vm_end - addr)
 | 
				
			||||||
 | 
							goto Efault;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) {
 | 
				
			||||||
 | 
							if (new_len > old_len)
 | 
				
			||||||
 | 
								goto Efault;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vma->vm_flags & VM_LOCKED) {
 | 
				
			||||||
 | 
							unsigned long locked, lock_limit;
 | 
				
			||||||
 | 
							locked = mm->locked_vm << PAGE_SHIFT;
 | 
				
			||||||
 | 
							lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
 | 
				
			||||||
 | 
							locked += new_len - old_len;
 | 
				
			||||||
 | 
							if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 | 
				
			||||||
 | 
								goto Eagain;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT))
 | 
				
			||||||
 | 
							goto Enomem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vma->vm_flags & VM_ACCOUNT) {
 | 
				
			||||||
 | 
							unsigned long charged = (new_len - old_len) >> PAGE_SHIFT;
 | 
				
			||||||
 | 
							if (security_vm_enough_memory(charged))
 | 
				
			||||||
 | 
								goto Efault;
 | 
				
			||||||
 | 
							*p = charged;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return vma;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Efault:	/* very odd choice for most of the cases, but... */
 | 
				
			||||||
 | 
						return ERR_PTR(-EFAULT);
 | 
				
			||||||
 | 
					Einval:
 | 
				
			||||||
 | 
						return ERR_PTR(-EINVAL);
 | 
				
			||||||
 | 
					Enomem:
 | 
				
			||||||
 | 
						return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
					Eagain:
 | 
				
			||||||
 | 
						return ERR_PTR(-EAGAIN);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Expand (or shrink) an existing mapping, potentially moving it at the
 | 
					 * Expand (or shrink) an existing mapping, potentially moving it at the
 | 
				
			||||||
 * same time (controlled by the MREMAP_MAYMOVE flag and available VM space)
 | 
					 * same time (controlled by the MREMAP_MAYMOVE flag and available VM space)
 | 
				
			||||||
| 
						 | 
					@ -340,39 +392,10 @@ unsigned long do_mremap(unsigned long addr,
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Ok, we need to grow..  or relocate.
 | 
						 * Ok, we need to grow..  or relocate.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	ret = -EFAULT;
 | 
						vma = vma_to_resize(addr, old_len, new_len, &charged);
 | 
				
			||||||
	vma = find_vma(mm, addr);
 | 
						if (IS_ERR(vma)) {
 | 
				
			||||||
	if (!vma || vma->vm_start > addr)
 | 
							ret = PTR_ERR(vma);
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (is_vm_hugetlb_page(vma)) {
 | 
					 | 
				
			||||||
		ret = -EINVAL;
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* We can't remap across vm area boundaries */
 | 
					 | 
				
			||||||
	if (old_len > vma->vm_end - addr)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) {
 | 
					 | 
				
			||||||
		if (new_len > old_len)
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (vma->vm_flags & VM_LOCKED) {
 | 
					 | 
				
			||||||
		unsigned long locked, lock_limit;
 | 
					 | 
				
			||||||
		locked = mm->locked_vm << PAGE_SHIFT;
 | 
					 | 
				
			||||||
		lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
 | 
					 | 
				
			||||||
		locked += new_len - old_len;
 | 
					 | 
				
			||||||
		ret = -EAGAIN;
 | 
					 | 
				
			||||||
		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT)) {
 | 
					 | 
				
			||||||
		ret = -ENOMEM;
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (vma->vm_flags & VM_ACCOUNT) {
 | 
					 | 
				
			||||||
		charged = (new_len - old_len) >> PAGE_SHIFT;
 | 
					 | 
				
			||||||
		if (security_vm_enough_memory(charged))
 | 
					 | 
				
			||||||
			goto out_nc;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* old_len exactly to the end of the area..
 | 
						/* old_len exactly to the end of the area..
 | 
				
			||||||
| 
						 | 
					@ -430,7 +453,6 @@ unsigned long do_mremap(unsigned long addr,
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	if (ret & ~PAGE_MASK)
 | 
						if (ret & ~PAGE_MASK)
 | 
				
			||||||
		vm_unacct_memory(charged);
 | 
							vm_unacct_memory(charged);
 | 
				
			||||||
out_nc:
 | 
					 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue