Skip to content

Commit 2f1c661

Browse files
lorenzo-stoakesakpm00
authored andcommitted
mm: introduce vma_merge_struct and abstract vma_merge(),vma_modify()
Rather than passing around huge numbers of parameters to numerous helper functions, abstract them into a single struct that we thread through the operation, the vma_merge_struct ('vmg'). Adjust vma_merge() and vma_modify() to accept this parameter, as well as predicate functions can_vma_merge_before(), can_vma_merge_after(), and the vma_modify_...() helper functions. Also introduce VMG_STATE() and VMG_VMA_STATE() helper macros to allow for easy vmg declaration. We additionally remove the requirement that vma_merge() is passed a VMA object representing the candidate new VMA. Previously it used this to obtain the mm_struct, file and anon_vma properties of the proposed range (a rather confusing state of affairs), which are now provided by the vmg directly. We also remove the pgoff calculation previously performed vma_modify(), and instead calculate this in VMG_VMA_STATE() via the vma_pgoff_offset() helper. Link: https://lkml.kernel.org/r/a955aad09d81329f6fbeb636b2dd10cde7b73dab.1725040657.git.lorenzo.stoakes@oracle.com Signed-off-by: Lorenzo Stoakes <[email protected]> Reviewed-by: Liam R. Howlett <[email protected]> Cc: Mark Brown <[email protected]> Cc: Vlastimil Babka <[email protected]> Cc: Bert Karwatzki <[email protected]> Cc: Jeff Xu <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Kees Cook <[email protected]> Cc: Lorenzo Stoakes <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: "Paul E. McKenney" <[email protected]> Cc: Paul Moore <[email protected]> Cc: Sidhartha Kumar <[email protected]> Cc: Suren Baghdasaryan <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 955db39 commit 2f1c661

File tree

4 files changed

+246
-207
lines changed

4 files changed

+246
-207
lines changed

mm/mmap.c

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,10 +1373,11 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
13731373
unsigned long end = addr + len;
13741374
unsigned long merge_start = addr, merge_end = end;
13751375
bool writable_file_mapping = false;
1376-
pgoff_t vm_pgoff;
13771376
int error = -ENOMEM;
13781377
VMA_ITERATOR(vmi, mm, addr);
1378+
VMG_STATE(vmg, mm, &vmi, addr, end, vm_flags, pgoff);
13791379

1380+
vmg.file = file;
13801381
/* Find the first overlapping VMA */
13811382
vma = vma_find(&vmi, end);
13821383
init_vma_munmap(&vms, &vmi, vma, addr, end, uf, /* unlock = */ false);
@@ -1389,12 +1390,12 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
13891390
if (error)
13901391
goto gather_failed;
13911392

1392-
next = vms.next;
1393-
prev = vms.prev;
1393+
next = vmg.next = vms.next;
1394+
prev = vmg.prev = vms.prev;
13941395
vma = NULL;
13951396
} else {
1396-
next = vma_next(&vmi);
1397-
prev = vma_prev(&vmi);
1397+
next = vmg.next = vma_next(&vmi);
1398+
prev = vmg.prev = vma_prev(&vmi);
13981399
if (prev)
13991400
vma_iter_next_range(&vmi);
14001401
}
@@ -1414,6 +1415,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
14141415

14151416
vms.nr_accounted = 0;
14161417
vm_flags |= VM_ACCOUNT;
1418+
vmg.flags = vm_flags;
14171419
}
14181420

14191421
if (vm_flags & VM_SPECIAL)
@@ -1422,28 +1424,31 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
14221424
/* Attempt to expand an old mapping */
14231425
/* Check next */
14241426
if (next && next->vm_start == end && !vma_policy(next) &&
1425-
can_vma_merge_before(next, vm_flags, NULL, file, pgoff+pglen,
1426-
NULL_VM_UFFD_CTX, NULL)) {
1427+
can_vma_merge_before(&vmg)) {
14271428
merge_end = next->vm_end;
14281429
vma = next;
1429-
vm_pgoff = next->vm_pgoff - pglen;
1430+
vmg.pgoff = next->vm_pgoff - pglen;
1431+
/*
1432+
* We set this here so if we will merge with the previous VMA in
1433+
* the code below, can_vma_merge_after() ensures anon_vma
1434+
* compatibility between prev and next.
1435+
*/
1436+
vmg.anon_vma = vma->anon_vma;
1437+
vmg.uffd_ctx = vma->vm_userfaultfd_ctx;
14301438
}
14311439

14321440
/* Check prev */
14331441
if (prev && prev->vm_end == addr && !vma_policy(prev) &&
1434-
(vma ? can_vma_merge_after(prev, vm_flags, vma->anon_vma, file,
1435-
pgoff, vma->vm_userfaultfd_ctx, NULL) :
1436-
can_vma_merge_after(prev, vm_flags, NULL, file, pgoff,
1437-
NULL_VM_UFFD_CTX, NULL))) {
1442+
can_vma_merge_after(&vmg)) {
14381443
merge_start = prev->vm_start;
14391444
vma = prev;
1440-
vm_pgoff = prev->vm_pgoff;
1445+
vmg.pgoff = prev->vm_pgoff;
14411446
vma_prev(&vmi); /* Equivalent to going to the previous range */
14421447
}
14431448

14441449
if (vma) {
14451450
/* Actually expand, if possible */
1446-
if (!vma_expand(&vmi, vma, merge_start, merge_end, vm_pgoff, next)) {
1451+
if (!vma_expand(&vmi, vma, merge_start, merge_end, vmg.pgoff, next)) {
14471452
khugepaged_enter_vma(vma, vm_flags);
14481453
goto expanded;
14491454
}
@@ -1774,26 +1779,29 @@ static int do_brk_flags(struct vma_iterator *vmi, struct vm_area_struct *vma,
17741779
* Expand the existing vma if possible; Note that singular lists do not
17751780
* occur after forking, so the expand will only happen on new VMAs.
17761781
*/
1777-
if (vma && vma->vm_end == addr && !vma_policy(vma) &&
1778-
can_vma_merge_after(vma, flags, NULL, NULL,
1779-
addr >> PAGE_SHIFT, NULL_VM_UFFD_CTX, NULL)) {
1780-
vma_iter_config(vmi, vma->vm_start, addr + len);
1781-
if (vma_iter_prealloc(vmi, vma))
1782-
goto unacct_fail;
1783-
1784-
vma_start_write(vma);
1785-
1786-
init_vma_prep(&vp, vma);
1787-
vma_prepare(&vp);
1788-
vma_adjust_trans_huge(vma, vma->vm_start, addr + len, 0);
1789-
vma->vm_end = addr + len;
1790-
vm_flags_set(vma, VM_SOFTDIRTY);
1791-
vma_iter_store(vmi, vma);
1792-
1793-
vma_complete(&vp, vmi, mm);
1794-
validate_mm(mm);
1795-
khugepaged_enter_vma(vma, flags);
1796-
goto out;
1782+
if (vma && vma->vm_end == addr && !vma_policy(vma)) {
1783+
VMG_STATE(vmg, mm, vmi, addr, addr + len, flags, PHYS_PFN(addr));
1784+
1785+
vmg.prev = vma;
1786+
if (can_vma_merge_after(&vmg)) {
1787+
vma_iter_config(vmi, vma->vm_start, addr + len);
1788+
if (vma_iter_prealloc(vmi, vma))
1789+
goto unacct_fail;
1790+
1791+
vma_start_write(vma);
1792+
1793+
init_vma_prep(&vp, vma);
1794+
vma_prepare(&vp);
1795+
vma_adjust_trans_huge(vma, vma->vm_start, addr + len, 0);
1796+
vma->vm_end = addr + len;
1797+
vm_flags_set(vma, VM_SOFTDIRTY);
1798+
vma_iter_store(vmi, vma);
1799+
1800+
vma_complete(&vp, vmi, mm);
1801+
validate_mm(mm);
1802+
khugepaged_enter_vma(vma, flags);
1803+
goto out;
1804+
}
17971805
}
17981806

17991807
if (vma)

0 commit comments

Comments
 (0)