rendered paste body/* This must be called under the mmap_sem. */
int anon_vma_prepare(struct vm_area_struct *vma)
{
struct anon_vma *anon_vma = vma->anon_vma;
might_sleep();
if (unlikely(!anon_vma)) {
struct mm_struct *mm = vma->vm_mm;
struct anon_vma *allocated, *locked;
anon_vma = find_mergeable_anon_vma(vma);
if (anon_vma) {
allocated = NULL;
locked = anon_vma;
spin_lock(&locked->lock);
} else {
anon_vma = anon_vma_alloc();
if (unlikely(!anon_vma))
return -ENOMEM;
allocated = anon_vma;
locked = NULL;
}
/* page_table_lock to protect against threads */
spin_lock(&mm->page_table_lock);
if (likely(!vma->anon_vma)) {
vma->anon_vma = anon_vma;
list_add(&vma->anon_vma_node, &anon_vma->head);
allocated = NULL;
}
#ifdef CONFIG_PAX_SEGMEXEC
if (vma->vm_flags & VM_MIRROR) {
struct vm_area_struct *vma_m;
vma_m = find_vma(vma->vm_mm, vma->vm_start + vma->vm_mirror);
BUG_ON(!vma_m || vma_m->vm_start != vma->vm_start + vma->vm_mirror);
BUG_ON(vma_m->anon_vma || vma->vm_pgoff != vma_m->vm_pgoff);
vma_m->anon_vma = anon_vma;
__anon_vma_link(vma_m);
}
#endif
spin_unlock(&mm->page_table_lock);
if (locked)
spin_unlock(&locked->lock);
if (unlikely(allocated))
anon_vma_free(allocated);
}
return 0;
}