Chapter 4: Virtual Process Memory
can_vma_merge_afterhelper function. The work of merging a region with its predecessor region looks
like this:
mm/mmap.c
if (prev && prev->vm_end == addr &&
can_vma_merge_after(prev, vm_flags,
anon_vma, file, pgoff)) {
...
If it can, the kernel then checks whether the successor region can and must be merged.
mm/mmap.c
/*
* OK, it can. Can we now merge in the successor as well?
*/
if (next && end == next->vm_start &&
can_vma_merge_before(next, vm_flags,
anon_vma, file, pgoff+pglen) &&
is_mergeable_anon_vma(prev->anon_vma,
next->anon_vma)) {
vma_adjust(prev, prev->vm_start,
next->vm_end, prev->vm_pgoff, NULL);
} else
vma_adjust(prev, prev->vm_start,
end, prev->vm_pgoff, NULL);
return prev;
}
The first difference as compared to the previous case is thatcan_vma_merge_beforeis used instead of
can_vma_merge_afterto check whether the two regions can be merged. If both the predecessor and the
successor region can be merged with the current region, it must also be ensured that the anonymous
mappings of the predecessor can be merged with those of the successor before a single region consisting
of all three regions can be created.
In both cases, the helper functionvma_adjustis invoked to perform final merging; it appropriately
modifies all data structures involved — the priority tree and thevm_area_structinstances — as well as
deallocating the instances of these structures that are no longer needed.
4.5.3 Inserting Regions
insert_vm_structis the standard function used by the kernel to insert new regions. The actual work is
delegated to two helper functions, as the code flow diagram in Figure 4-11 shows.
find_vma_prepareis first invoked to obtain the information listed below by reference to the start address
of the new region and of the address space involved (mm_struct).
❑ Thevm_area_structinstance of the preceding address space.
❑ The parent node (in the red-black tree) in which the node for the new region is held.
❑ The leaf node (of the red-black tree) that contains the region itself.