|
|
int expand_stack(struct vm_area_struct * vma, unsigned long address) | int expand_stack(struct vm_area_struct * vma, unsigned long address) |
{ | { |
int error; | int error; |
unsigned long size, grow; |
|
| |
if (!(vma->vm_flags & VM_GROWSUP)) | if (!(vma->vm_flags & VM_GROWSUP)) |
return -EFAULT; | return -EFAULT; |
|
|
*/ | */ |
address += 4 + PAGE_SIZE - 1; | address += 4 + PAGE_SIZE - 1; |
address &= PAGE_MASK; | address &= PAGE_MASK; |
size = address - vma->vm_start; |
error = 0; |
grow = (address - vma->vm_end) >> PAGE_SHIFT; |
|
| |
error = acct_stack_growth(vma, size, grow); |
/* Somebody else might have raced and expanded it already */ |
if (!error) |
if (address > vma->vm_end) { |
vma->vm_end = address; |
unsigned long size, grow; |
|
|
|
size = address - vma->vm_start; |
|
grow = (address - vma->vm_end) >> PAGE_SHIFT; |
|
|
|
error = acct_stack_growth(vma, size, grow); |
|
if (!error) |
|
vma->vm_end = address; |
|
} |
anon_vma_unlock(vma); | anon_vma_unlock(vma); |
return error; | return error; |
} | } |
|
|
int expand_stack(struct vm_area_struct *vma, unsigned long address) | int expand_stack(struct vm_area_struct *vma, unsigned long address) |
{ | { |
int error; | int error; |
unsigned long size, grow; |
|
| |
/* | /* |
* We must make sure the anon_vma is allocated | * We must make sure the anon_vma is allocated |
|
|
* anon_vma lock to serialize against concurrent expand_stacks. | * anon_vma lock to serialize against concurrent expand_stacks. |
*/ | */ |
address &= PAGE_MASK; | address &= PAGE_MASK; |
size = vma->vm_end - address; |
error = 0; |
grow = (vma->vm_start - address) >> PAGE_SHIFT; |
|
| |
error = acct_stack_growth(vma, size, grow); |
/* Somebody else might have raced and expanded it already */ |
if (!error) { |
if (address < vma->vm_start) { |
vma->vm_start = address; |
unsigned long size, grow; |
vma->vm_pgoff -= grow; |
|
|
size = vma->vm_end - address; |
|
grow = (vma->vm_start - address) >> PAGE_SHIFT; |
|
|
|
error = acct_stack_growth(vma, size, grow); |
|
if (!error) { |
|
vma->vm_start = address; |
|
vma->vm_pgoff -= grow; |
|
} |
} | } |
anon_vma_unlock(vma); | anon_vma_unlock(vma); |
return error; | return error; |