}
static inline unsigned long detach_range(struct mm_struct *mm,
- struct ma_state *src, struct ma_state *dst,
- struct vm_area_struct *prev, struct vm_area_struct **last)
+ struct ma_state *src, struct ma_state *dst, struct vm_area_struct *vma,
+ struct vm_area_struct *prev, struct vm_area_struct **last)
{
- struct vm_area_struct *tmp;
int count = 0;
struct ma_state mas;
* area.
*/
mas = *src;
- mas_set(&mas, src->index);
- mas_for_each(&mas, tmp, src->last) {
- *last = tmp;
+ mas.last = src->index;
+ do {
+ BUG_ON(vma->vm_start < src->index);
+ BUG_ON(vma->vm_end > (src->last + 1));
+ *last = vma;
count++;
- if (tmp->vm_flags & VM_LOCKED) {
- mm->locked_vm -= vma_pages(tmp);
- munlock_vma_pages_all(tmp);
+ if (vma->vm_flags & VM_LOCKED) {
+ mm->locked_vm -= vma_pages(vma);
+ munlock_vma_pages_all(vma);
}
- vma_mas_store(tmp, dst);
- }
+ vma_mas_store(vma, dst);
+ } while ((vma = mas_find(&mas, src->last)) != NULL);
- /* Decrement map_count */
- mm->map_count -= count;
/* Find the one after the series before overwrite */
- tmp = mas_find(&mas, ULONG_MAX);
+ mas.index = mas.last = src->last + 1;
+ vma = mas_find(&mas, -1);
/* Drop removed area from the tree */
mas_store_gfp(src, NULL, GFP_KERNEL);
+ /* Decrement map_count */
+ mm->map_count -= count;
/* Set the upper limit */
- if (!tmp)
+ if (!vma)
return USER_PGTABLES_CEILING;
- return tmp->vm_start;
+ return vma->vm_start;
}
/* do_mas_align_munmap() - munmap the aligned region from @start to @end.
return error;
prev = vma;
// Split invalidated node, reset.
- mas->index = start;
- mas_reset(mas);
- vma = mas_walk(mas);
+ mas_set_range(mas, start, end - 1);
} else {
tmp = *mas;
prev = mas_prev(&tmp, 0);
last = vma;
else {
tmp = *mas;
- mas_reset(&tmp);
mas_set(&tmp, end - 1);
last = mas_walk(&tmp);
}
if (error)
return error;
// Split invalidated node, reset.
- mas->index = start;
- mas_reset(mas);
- vma = mas_walk(mas);
+ mas_set_range(mas, start, end - 1);
+
}
+ if (mas->node == MAS_START)
+ vma = mas_walk(mas);
if (unlikely(uf)) {
/*
}
/* Point of no return */
- max = detach_range(mm, mas, &dst, prev, &last);
+ max = detach_range(mm, mas, &dst, vma, prev, &last);
/*
* Do not downgrade mmap_lock if we are next to VM_GROWSDOWN or
mmap_write_downgrade(mm);
}
- mas_reset(&dst);
+ /* Unmap the region */
mas_set(&dst, start);
+ tmp = dst;
vma = mas_walk(&dst);
unmap_region(mm, vma, &dst, start, end, prev, max);
- /* Fix up all other VM information */
- mas_reset(&dst);
- mas_set(&dst, start);
+ /* Statistics and freeing VMAs */
+ dst = tmp;
remove_mt(mm, &dst);
return downgrade ? 1 : 0;
unsigned long end;
struct vm_area_struct *vma;
- if ((offset_in_page(start)) || start > TASK_SIZE || len > TASK_SIZE-start)
+ if ((offset_in_page(start)) || (start > TASK_SIZE) ||
+ (len > TASK_SIZE - start))
return -EINVAL;
end = start + PAGE_ALIGN(len);
if (!vma)
return 0;
-// printk("vma found at %lx %lu\n", vma->vm_start, vma->vm_end);
- mas_set_range(mas, start, end - 1);
+ mas->last = end - 1;
return do_mas_align_munmap(mas, vma, mm, start, end, uf, downgrade);
}
/* do_munmap() - Wrapper function for non-maple tree aware do_munmap() calls.
vm_flags |= VM_ACCOUNT;
}
- mas_reset(&mas);
mas_set_range(&mas, addr, end - 1);
if (vm_flags & VM_SPECIAL) {
ma_prev = mas;
// Very likely a shorter walk.
mas = ma_prev;
- mas_set_range(&mas, addr, end - 1);
+ mas.last = end - 1;
+ mas.index = addr;
mas_walk(&mas);
vma_mas_link(mm, vma, &mas);
arch_unmap(mm, newbrk, oldbrk);
if (likely(vma->vm_start >= newbrk)) { // remove entire mapping(s)
+ mas->last = oldbrk - 1;
ret = do_mas_align_munmap(mas, vma, mm, newbrk, oldbrk, uf, true);
goto munmap_full_vma;
}
munlock_vma_pages_all(vma);
}
}
- mas_reset(&mas);
mas_set(&mas, FIRST_USER_ADDRESS);
}
return;
mas2 = mas;
- mas_reset(&mas);
mas_set(&mas, FIRST_USER_ADDRESS);
lru_add_drain();
* Walk the list again, actually closing and freeing it,
* with preemption enabled, without holding any MM locks.
*/
- mas_reset(&mas);
mas_set(&mas, 0);
mas_for_each(&mas, vma, -1) {
if (vma->vm_flags & VM_ACCOUNT)
vm_lock_mapping(mm, vma->vm_file->f_mapping);
}
- mas_reset(&mas);
mas_set(&mas, 0);
mas_for_each(&mas, vma, ULONG_MAX) {
if (signal_pending(current))
vm_lock_mapping(mm, vma->vm_file->f_mapping);
}
- mas_reset(&mas);
mas_set(&mas, 0);
mas_for_each(&mas, vma, ULONG_MAX) {
if (signal_pending(current))