• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 static unsigned long pgsz;
25 static char *addr;
26 
verify_mlock2(void)27 static 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 
69 end:
70 	SAFE_MUNLOCK(addr, pgsz);
71 }
72 
setup(void)73 static void setup(void)
74 {
75 	pgsz = getpagesize();
76 	addr = SAFE_MMAP(NULL, pgsz, PROT_WRITE,
77 			 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
78 }
79 
cleanup(void)80 static void cleanup(void)
81 {
82 	if (addr)
83 		SAFE_MUNMAP(addr, pgsz);
84 }
85 
86 static struct tst_test test = {
87 	.test_all = verify_mlock2,
88 	.setup = setup,
89 	.cleanup = cleanup,
90 	.needs_root = 1,
91 };
92