First phase scanning the memory regions

The do_munmap( ) function executes the following steps:

1. Performs some preliminary checks on the parameter values. If the linear address interval includes addresses greater than task_size, if addr is not a multiple of 4,096, or if the linear address interval has a zero length, it returns the error code -einval.

2. Locates the first memory region that overlaps the linear address interval to be deleted:

mpnt = find_vma_prev(current->mm, addr, &prev);

if (!mpnt || mpnt->vm_start >= addr + len) return 0;

3. If the linear address interval is located inside a memory region, its deletion splits the region into two smaller ones. In this case, do_munmap( ) checks whether current is allowed to obtain an additional memory region:

if ((mpnt->vm_start < addr && mpnt->vm_end > addr + len) && current->mm->map_count > MAX_MAP_COUNT) return -ENOMEM;

4. Attempts to get a new vm_area_struct descriptor. There may be no need for it, but the function makes the request anyway so that it can terminate right away if the allocation fails. This cautious approach simplifies the code since it allows an easy error exit.

5. Builds up a list that includes all descriptors of the memory regions that overlap the linear address interval. This list is created by setting the vm_next field of the memory region descriptor (temporarily) so it points to the previous item in the list; this field thus acts as a backward link. As each region is added to this backward list, a local variable named free points to the last inserted element. The regions inserted in the list are also removed from the list of memory regions owned by the process and from the red-black tree (by means of the rb_erase( ) function):

npp = (prev ? &prev->vm_next : &current->mm->mmap); free = NULL;

spin_lock(&current->mm->page_table_lock);

for ( ; mpnt && mpnt->vm_start < addr + len; mpnt = *npp) { *npp = mpnt->vm_next; mpnt->vm_next = free; free = mpnt;

rb_erase(&mpnt->vm_rb, &current->mm->mm_rb);

current->mm->mmap_cache = NULL; spin_unlock(&current->mm->page_table_lock);

Was this article helpful?

0 0

Post a comment