As pages are faulted in MLOCK_ONFAULT correctly updates /proc/self/smaps, but doesn't update /proc/meminfo's Mlocked field. - Before this /proc/meminfo fields didn't change as pages were faulted in: = Start = /proc/meminfo Unevictable: 10128 kB Mlocked: 10132 kB = Creating testfile = = after mlock2(MLOCK_ONFAULT) = /proc/meminfo Unevictable: 10128 kB Mlocked: 10132 kB /proc/self/smaps 7f8714000000-7f8754000000 rw-s 00000000 08:04 50857050 /root/testfile Locked: 0 kB = after reading half of the file = /proc/meminfo Unevictable: 10128 kB Mlocked: 10132 kB /proc/self/smaps 7f8714000000-7f8754000000 rw-s 00000000 08:04 50857050 /root/testfile Locked: 524288 kB = after reading the entire the file = /proc/meminfo Unevictable: 10128 kB Mlocked: 10132 kB /proc/self/smaps 7f8714000000-7f8754000000 rw-s 00000000 08:04 50857050 /root/testfile Locked: 1048576 kB = after munmap = /proc/meminfo Unevictable: 10128 kB Mlocked: 10132 kB /proc/self/smaps - After: /proc/meminfo fields are properly updated as pages are touched: = Start = /proc/meminfo Unevictable: 60 kB Mlocked: 60 kB = Creating testfile = = after mlock2(MLOCK_ONFAULT) = /proc/meminfo Unevictable: 60 kB Mlocked: 60 kB /proc/self/smaps 7f2b9c600000-7f2bdc600000 rw-s 00000000 08:04 63045798 /root/testfile Locked: 0 kB = after reading half of the file = /proc/meminfo Unevictable: 524220 kB Mlocked: 524220 kB /proc/self/smaps 7f2b9c600000-7f2bdc600000 rw-s 00000000 08:04 63045798 /root/testfile Locked: 524288 kB = after reading the entire the file = /proc/meminfo Unevictable: 1048496 kB Mlocked: 1048508 kB /proc/self/smaps 7f2b9c600000-7f2bdc600000 rw-s 00000000 08:04 63045798 /root/testfile Locked: 1048576 kB = after munmap = /proc/meminfo Unevictable: 176 kB Mlocked: 60 kB /proc/self/smaps Repro code. --- int mlock2wrap(const void* addr, size_t len, int flags) { return syscall(SYS_mlock2, addr, len, flags); } void smaps() { char smapscmd[1000]; snprintf( smapscmd, sizeof(smapscmd) - 1, "grep testfile -A 20 /proc/%d/smaps | grep -E '(testfile|Locked)'", getpid()); printf("/proc/self/smaps\n"); fflush(stdout); system(smapscmd); } void meminfo() { const char* meminfocmd = "grep -E '(Mlocked|Unevictable)' /proc/meminfo"; printf("/proc/meminfo\n"); fflush(stdout); system(meminfocmd); } { \ int rc = (call); \ if (rc != 0) { \ printf("error %d %s\n", rc, strerror(errno)); \ exit(1); \ } \ } int main(int argc, char* argv[]) { printf("= Start =\n"); meminfo(); printf("= Creating testfile =\n"); size_t size = 1 << 30; // 1 GiB int fd = open("testfile", O_CREAT | O_RDWR, 0666); { void* buf = malloc(size); write(fd, buf, size); free(buf); } int ret = 0; void* addr = NULL; addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (argc > 1) { PCHECK(mlock2wrap(addr, size, MLOCK_ONFAULT)); printf("= after mlock2(MLOCK_ONFAULT) =\n"); meminfo(); smaps(); for (size_t i = 0; i < size / 2; i += 4096) { ret += ((char*)addr)[i]; } printf("= after reading half of the file =\n"); meminfo(); smaps(); for (size_t i = 0; i < size; i += 4096) { ret += ((char*)addr)[i]; } printf("= after reading the entire the file =\n"); meminfo(); smaps(); } else { PCHECK(mlock(addr, size)); printf("= after mlock =\n"); meminfo(); smaps(); } PCHECK(munmap(addr, size)); printf("= after munmap =\n"); meminfo(); smaps(); return ret; } --- Signed-off-by: Lucian Adrian Grijincu <lucian@xxxxxx> Acked-by: Souptick Joarder <jrdr.linux@xxxxxxxxx> --- mm/memory.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/memory.c b/mm/memory.c index e0c232fe81d9..55da24f33bc4 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3311,6 +3311,8 @@ vm_fault_t alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg, } else { inc_mm_counter_fast(vma->vm_mm, mm_counter_file(page)); page_add_file_rmap(page, false); + if (vma->vm_flags & VM_LOCKED && !PageTransCompound(page)) + mlock_vma_page(page); } set_pte_at(vma->vm_mm, vmf->address, vmf->pte, entry); -- 2.17.1