1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. 4 * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> 5 */ 6/* 7 * Description: 8 * If one memory is already locked by mlock2() with MLOCK_ONFAULT and then 9 * it is locked again by mlock()(or mlock2() without MLOCK_ONFAULT), the 10 * VmLck field in /proc/pid/status should increase once instead of twice. 11 * 12 * This issue has been fixed in kernel: 13 * 'b155b4fde5bd("mm: mlock: avoid increase mm->locked_vm on mlock() when already mlock2(,MLOCK_ONFAULT)")' 14 */ 15#include <errno.h> 16#include <unistd.h> 17#include <sys/mman.h> 18#include <linux/mman.h> 19 20#include "tst_test.h" 21#include "lapi/syscalls.h" 22#include "lapi/mlock2.h" 23 24static unsigned long pgsz; 25static char *addr; 26 27static void verify_mlock2(void) 28{ 29 unsigned long bsize, asize1, asize2; 30 31 SAFE_FILE_LINES_SCANF("/proc/self/status", "VmLck: %lu", &bsize); 32 33 TEST(tst_syscall(__NR_mlock2, addr, pgsz, MLOCK_ONFAULT)); 34 if (TST_RET != 0) { 35 if (TST_ERR == EINVAL) { 36 tst_res(TCONF, 37 "mlock2() didn't support MLOCK_ONFAULT"); 38 } else { 39 tst_res(TFAIL | TTERRNO, 40 "mlock2(MLOCK_ONFAULT) failed"); 41 } 42 return; 43 } 44 45 SAFE_FILE_LINES_SCANF("/proc/self/status", "VmLck: %lu", &asize1); 46 47 if ((asize1 - bsize) * 1024 != pgsz) { 48 tst_res(TFAIL, 49 "mlock2(MLOCK_ONFAULT) locked %lu size, expected %lu", 50 (asize1 - bsize) * 1024, pgsz); 51 goto end; 52 } 53 54 TEST(tst_syscall(__NR_mlock2, addr, pgsz, 0)); 55 if (TST_RET != 0) { 56 tst_res(TFAIL | TTERRNO, "mlock2() failed"); 57 goto end; 58 } 59 60 SAFE_FILE_LINES_SCANF("/proc/self/status", "VmLck: %lu", &asize2); 61 62 if (asize1 != asize2) { 63 tst_res(TFAIL, "Locking one memory again increased VmLck"); 64 } else { 65 tst_res(TPASS, 66 "Locking one memory again didn't increased VmLck"); 67 } 68 69end: 70 SAFE_MUNLOCK(addr, pgsz); 71} 72 73static void setup(void) 74{ 75 pgsz = getpagesize(); 76 addr = SAFE_MMAP(NULL, pgsz, PROT_WRITE, 77 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 78} 79 80static void cleanup(void) 81{ 82 if (addr) 83 SAFE_MUNMAP(addr, pgsz); 84} 85 86static struct tst_test test = { 87 .test_all = verify_mlock2, 88 .setup = setup, 89 .cleanup = cleanup, 90 .needs_root = 1, 91}; 92