On 8/2/23 23:12, Ryan Roberts wrote: >>> I also wonder if you should change the name of folio_within_vma() to something >>> like folio_test_cont_in_vma() to disambiguate from the case where the folio may >>> be fully mapped with a discontiguity (although perhaps that's not possible >>> because a mremap would result in distinct vmas... would a new mmap in the hole >>> cause a merge of all 3?). >> I don't think it's possible as mremap reuse original pgoff of VMA to new VMA. I suppose >> it will prevent VMA merging. But I didn't check detail. > > pgoff is not relevant for anon though, right? anonymous folio->index is related with vma->vm_pgoff. > > FWIW, I wrote a test to check if merging is performed. Interestingly, v5.4 (on x86) *does* merge the VMAs in this case, but v6.5-rc3 (on arm64) *does not* merge the VMAs in this case. What if you fault in the pages to the mapped VMAs? > > I think you should assume it might be possible in some cases. I don't think mremap target VMA could be merged with prev/next unless it's merged back (move the pieces large folio together). Regards Yin, Fengwei > > > #define _GNU_SOURCE > #include <stdlib.h> > #include <stdio.h> > #include <sys/mman.h> > #include <unistd.h> > > int main(int argc, char **argv) > { > size_t pgsize = getpagesize(); > char *memarea; > char *memlow; > char *memmid; > char *memhigh; > int ret = 0; > > // Get a free vm area big enough for 5 pages. > memarea = mmap(NULL, pgsize * 5, > PROT_NONE, > MAP_PRIVATE | MAP_ANONYMOUS, > -1, 0); > if (memarea == MAP_FAILED) { > perror("mmap 1"); > exit(1); > } > > // Map 2 pages one page into allocated area. > memlow = mmap(memarea + pgsize, pgsize * 2, > PROT_READ | PROT_WRITE, > MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, > -1, 0); > if (memlow == MAP_FAILED) { > perror("mmap 2"); > exit(1); > } > > // Move the second allocated page one page higher. > memhigh = mremap(memarea + pgsize * 2, pgsize, pgsize, > MREMAP_FIXED | MREMAP_MAYMOVE, > memarea + pgsize * 3); > if (memhigh == MAP_FAILED) { > perror("mremap"); > exit(1); > } > > // We should now have: > // | page 0 | page 1 | page 2 | page 3 | page 4 | > // | NONE | vma 1 | empty | vma 2 | NONE | > printf("Check for 2 vmas with hole: pid=%d, memarea=%p, memlow=%p, memhigh=%p\n", > getpid(), memarea, memlow, memhigh); > getchar(); > > // Now map a page in the empty space. > memmid = mmap(memarea + pgsize * 2, pgsize, > PROT_READ | PROT_WRITE, > MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, > -1, 0); > if (memmid == MAP_FAILED) { > perror("mmap 2"); > exit(1); > } > > // We should now have: > // | page 0 | page 1 | page 2 | page 3 | page 4 | > // | NONE | vma 1 | NONE | > printf("Check for single merged vma: pid=%d, memarea=%p, memlow=%p, memmid=%p, memhigh=%p\n", > getpid(), memarea, memlow, memmid, memhigh); > getchar(); > > return ret; > } > > > > Output on v5.4: > > Check for 2 vmas with hole: pid=171038, memarea=0x7fe6c34d9000, memlow=0x7fe6c34da000, memhigh=0x7fe6c34dc000 > Check for single merged vma: pid=171038, memarea=0x7fe6c34d9000, memlow=0x7fe6c34da000, memmid=0x7fe6c34db000, memhigh=0x7fe6c34dc000 > > And maps output at the 2 check points: > > (base) ryarob01@e125769:/data_nvme0n1/ryarob01/granule_perf$ cat /proc/171038/maps > 55e55c258000-55e55c259000 r--p 00000000 fd:00 5297466 /data_nvme0n1/ryarob01/granule_perf/merge > 55e55c259000-55e55c25a000 r-xp 00001000 fd:00 5297466 /data_nvme0n1/ryarob01/granule_perf/merge > 55e55c25a000-55e55c25b000 r--p 00002000 fd:00 5297466 /data_nvme0n1/ryarob01/granule_perf/merge > 55e55c25b000-55e55c25c000 r--p 00002000 fd:00 5297466 /data_nvme0n1/ryarob01/granule_perf/merge > 55e55c25c000-55e55c25d000 rw-p 00003000 fd:00 5297466 /data_nvme0n1/ryarob01/granule_perf/merge > 55e55c403000-55e55c424000 rw-p 00000000 00:00 0 [heap] > 7fe6c32d2000-7fe6c32f4000 r--p 00000000 fd:02 9573653 /lib/x86_64-linux-gnu/libc-2.31.so > 7fe6c32f4000-7fe6c346c000 r-xp 00022000 fd:02 9573653 /lib/x86_64-linux-gnu/libc-2.31.so > 7fe6c346c000-7fe6c34ba000 r--p 0019a000 fd:02 9573653 /lib/x86_64-linux-gnu/libc-2.31.so > 7fe6c34ba000-7fe6c34be000 r--p 001e7000 fd:02 9573653 /lib/x86_64-linux-gnu/libc-2.31.so > 7fe6c34be000-7fe6c34c0000 rw-p 001eb000 fd:02 9573653 /lib/x86_64-linux-gnu/libc-2.31.so > 7fe6c34c0000-7fe6c34c6000 rw-p 00000000 00:00 0 > 7fe6c34d9000-7fe6c34da000 ---p 00000000 00:00 0 > 7fe6c34da000-7fe6c34db000 rw-p 00000000 00:00 0 > 7fe6c34dc000-7fe6c34dd000 rw-p 00000000 00:00 0 > 7fe6c34dd000-7fe6c34de000 ---p 00000000 00:00 0 > 7fe6c34de000-7fe6c34df000 r--p 00000000 fd:02 9573649 /lib/x86_64-linux-gnu/ld-2.31.so > 7fe6c34df000-7fe6c3502000 r-xp 00001000 fd:02 9573649 /lib/x86_64-linux-gnu/ld-2.31.so > 7fe6c3502000-7fe6c350a000 r--p 00024000 fd:02 9573649 /lib/x86_64-linux-gnu/ld-2.31.so > 7fe6c350b000-7fe6c350c000 r--p 0002c000 fd:02 9573649 /lib/x86_64-linux-gnu/ld-2.31.so > 7fe6c350c000-7fe6c350d000 rw-p 0002d000 fd:02 9573649 /lib/x86_64-linux-gnu/ld-2.31.so > 7fe6c350d000-7fe6c350e000 rw-p 00000000 00:00 0 > 7fff39a11000-7fff39a32000 rw-p 00000000 00:00 0 [stack] > 7fff39a83000-7fff39a86000 r--p 00000000 00:00 0 [vvar] > 7fff39a86000-7fff39a87000 r-xp 00000000 00:00 0 [vdso] > ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall] > (base) ryarob01@e125769:/data_nvme0n1/ryarob01/granule_perf$ cat /proc/171038/maps > 55e55c258000-55e55c259000 r--p 00000000 fd:00 5297466 /data_nvme0n1/ryarob01/granule_perf/merge > 55e55c259000-55e55c25a000 r-xp 00001000 fd:00 5297466 /data_nvme0n1/ryarob01/granule_perf/merge > 55e55c25a000-55e55c25b000 r--p 00002000 fd:00 5297466 /data_nvme0n1/ryarob01/granule_perf/merge > 55e55c25b000-55e55c25c000 r--p 00002000 fd:00 5297466 /data_nvme0n1/ryarob01/granule_perf/merge > 55e55c25c000-55e55c25d000 rw-p 00003000 fd:00 5297466 /data_nvme0n1/ryarob01/granule_perf/merge > 55e55c403000-55e55c424000 rw-p 00000000 00:00 0 [heap] > 7fe6c32d2000-7fe6c32f4000 r--p 00000000 fd:02 9573653 /lib/x86_64-linux-gnu/libc-2.31.so > 7fe6c32f4000-7fe6c346c000 r-xp 00022000 fd:02 9573653 /lib/x86_64-linux-gnu/libc-2.31.so > 7fe6c346c000-7fe6c34ba000 r--p 0019a000 fd:02 9573653 /lib/x86_64-linux-gnu/libc-2.31.so > 7fe6c34ba000-7fe6c34be000 r--p 001e7000 fd:02 9573653 /lib/x86_64-linux-gnu/libc-2.31.so > 7fe6c34be000-7fe6c34c0000 rw-p 001eb000 fd:02 9573653 /lib/x86_64-linux-gnu/libc-2.31.so > 7fe6c34c0000-7fe6c34c6000 rw-p 00000000 00:00 0 > 7fe6c34d9000-7fe6c34da000 ---p 00000000 00:00 0 > 7fe6c34da000-7fe6c34dd000 rw-p 00000000 00:00 0 > 7fe6c34dd000-7fe6c34de000 ---p 00000000 00:00 0 > 7fe6c34de000-7fe6c34df000 r--p 00000000 fd:02 9573649 /lib/x86_64-linux-gnu/ld-2.31.so > 7fe6c34df000-7fe6c3502000 r-xp 00001000 fd:02 9573649 /lib/x86_64-linux-gnu/ld-2.31.so > 7fe6c3502000-7fe6c350a000 r--p 00024000 fd:02 9573649 /lib/x86_64-linux-gnu/ld-2.31.so > 7fe6c350b000-7fe6c350c000 r--p 0002c000 fd:02 9573649 /lib/x86_64-linux-gnu/ld-2.31.so > 7fe6c350c000-7fe6c350d000 rw-p 0002d000 fd:02 9573649 /lib/x86_64-linux-gnu/ld-2.31.so > 7fe6c350d000-7fe6c350e000 rw-p 00000000 00:00 0 > 7fff39a11000-7fff39a32000 rw-p 00000000 00:00 0 [stack] > 7fff39a83000-7fff39a86000 r--p 00000000 00:00 0 [vvar] > 7fff39a86000-7fff39a87000 r-xp 00000000 00:00 0 [vdso] > ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall] > > > Output on v6.5-rc3: > > Check for 2 vmas with hole: pid=3181, memarea=0xfffff7ff2000, memlow=0xfffff7ff3000, memhigh=0xfffff7ff5000 > Check for single merged vma: pid=3181, memarea=0xfffff7ff2000, memlow=0xfffff7ff3000, memmid=0xfffff7ff4000, memhigh=0xfffff7ff5000 > > And maps output at the 2 check points: > > ubuntu@ubuntuvm:~/linux$ cat /proc/3181/maps > aaaaaaaa0000-aaaaaaaa1000 r-xp 00000000 fe:02 8199010 /home/ubuntu/merge > aaaaaaab0000-aaaaaaab1000 r--p 00000000 fe:02 8199010 /home/ubuntu/merge > aaaaaaab1000-aaaaaaab2000 rw-p 00001000 fe:02 8199010 /home/ubuntu/merge > aaaaaaab2000-aaaaaaad3000 rw-p 00000000 00:00 0 [heap] > fffff7e00000-fffff7f89000 r-xp 00000000 fe:02 41410085 /usr/lib/aarch64-linux-gnu/libc.so.6 > fffff7f89000-fffff7f98000 ---p 00189000 fe:02 41410085 /usr/lib/aarch64-linux-gnu/libc.so.6 > fffff7f98000-fffff7f9c000 r--p 00188000 fe:02 41410085 /usr/lib/aarch64-linux-gnu/libc.so.6 > fffff7f9c000-fffff7f9e000 rw-p 0018c000 fe:02 41410085 /usr/lib/aarch64-linux-gnu/libc.so.6 > fffff7f9e000-fffff7faa000 rw-p 00000000 00:00 0 > fffff7fc2000-fffff7fed000 r-xp 00000000 fe:02 41316494 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 > fffff7ff2000-fffff7ff3000 ---p 00000000 00:00 0 > fffff7ff3000-fffff7ff4000 rw-p 00000000 00:00 0 > fffff7ff5000-fffff7ff6000 rw-p 00000000 00:00 0 > fffff7ff6000-fffff7ff7000 ---p 00000000 00:00 0 > fffff7ff7000-fffff7ff9000 rw-p 00000000 00:00 0 > fffff7ff9000-fffff7ffb000 r--p 00000000 00:00 0 [vvar] > fffff7ffb000-fffff7ffc000 r-xp 00000000 00:00 0 [vdso] > fffff7ffc000-fffff7ffe000 r--p 0002a000 fe:02 41316494 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 > fffff7ffe000-fffff8000000 rw-p 0002c000 fe:02 41316494 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 > fffffffdf000-1000000000000 rw-p 00000000 00:00 0 [stack] > ubuntu@ubuntuvm:~/linux$ cat /proc/3181/maps > aaaaaaaa0000-aaaaaaaa1000 r-xp 00000000 fe:02 8199010 /home/ubuntu/merge > aaaaaaab0000-aaaaaaab1000 r--p 00000000 fe:02 8199010 /home/ubuntu/merge > aaaaaaab1000-aaaaaaab2000 rw-p 00001000 fe:02 8199010 /home/ubuntu/merge > aaaaaaab2000-aaaaaaad3000 rw-p 00000000 00:00 0 [heap] > fffff7e00000-fffff7f89000 r-xp 00000000 fe:02 41410085 /usr/lib/aarch64-linux-gnu/libc.so.6 > fffff7f89000-fffff7f98000 ---p 00189000 fe:02 41410085 /usr/lib/aarch64-linux-gnu/libc.so.6 > fffff7f98000-fffff7f9c000 r--p 00188000 fe:02 41410085 /usr/lib/aarch64-linux-gnu/libc.so.6 > fffff7f9c000-fffff7f9e000 rw-p 0018c000 fe:02 41410085 /usr/lib/aarch64-linux-gnu/libc.so.6 > fffff7f9e000-fffff7faa000 rw-p 00000000 00:00 0 > fffff7fc2000-fffff7fed000 r-xp 00000000 fe:02 41316494 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 > fffff7ff2000-fffff7ff3000 ---p 00000000 00:00 0 > fffff7ff3000-fffff7ff4000 rw-p 00000000 00:00 0 > fffff7ff4000-fffff7ff5000 rw-p 00000000 00:00 0 > fffff7ff5000-fffff7ff6000 rw-p 00000000 00:00 0 > fffff7ff6000-fffff7ff7000 ---p 00000000 00:00 0 > fffff7ff7000-fffff7ff9000 rw-p 00000000 00:00 0 > fffff7ff9000-fffff7ffb000 r--p 00000000 00:00 0 [vvar] > fffff7ffb000-fffff7ffc000 r-xp 00000000 00:00 0 [vdso] > fffff7ffc000-fffff7ffe000 r--p 0002a000 fe:02 41316494 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 > fffff7ffe000-fffff8000000 rw-p 0002c000 fe:02 41316494 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 > fffffffdf000-1000000000000 rw-p 00000000 00:00 0 [stack]