xref: /aosp_15_r20/external/ltp/testcases/kernel/mem/vma/vma02.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker /*
2*49cdfc7eSAndroid Build Coastguard Worker  * This is a reproducer from mainline commit
3*49cdfc7eSAndroid Build Coastguard Worker  * 9d8cebd4bcd7c3878462fdfda34bbcdeb4df7ef4:
4*49cdfc7eSAndroid Build Coastguard Worker  *
5*49cdfc7eSAndroid Build Coastguard Worker  * "Strangely, current mbind() doesn't merge vma with neighbor vma
6*49cdfc7eSAndroid Build Coastguard Worker  * although it's possible.  Unfortunately, many vma can reduce
7*49cdfc7eSAndroid Build Coastguard Worker  * performance..."
8*49cdfc7eSAndroid Build Coastguard Worker  *
9*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 2010  Red Hat, Inc.
10*49cdfc7eSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or
11*49cdfc7eSAndroid Build Coastguard Worker  * modify it under the terms of version 2 of the GNU General Public
12*49cdfc7eSAndroid Build Coastguard Worker  * License as published by the Free Software Foundation.
13*49cdfc7eSAndroid Build Coastguard Worker  *
14*49cdfc7eSAndroid Build Coastguard Worker  * This program is distributed in the hope that it would be useful,
15*49cdfc7eSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16*49cdfc7eSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17*49cdfc7eSAndroid Build Coastguard Worker  *
18*49cdfc7eSAndroid Build Coastguard Worker  * Further, this software is distributed without any warranty that it
19*49cdfc7eSAndroid Build Coastguard Worker  * is free of the rightful claim of any third person regarding
20*49cdfc7eSAndroid Build Coastguard Worker  * infringement or the like.  Any license provided herein, whether
21*49cdfc7eSAndroid Build Coastguard Worker  * implied or otherwise, applies only to this software file.  Patent
22*49cdfc7eSAndroid Build Coastguard Worker  * licenses, if any, provided herein do not apply to combinations of
23*49cdfc7eSAndroid Build Coastguard Worker  * this program with other software, or any other product whatsoever.
24*49cdfc7eSAndroid Build Coastguard Worker  *
25*49cdfc7eSAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License
26*49cdfc7eSAndroid Build Coastguard Worker  * along with this program; if not, write the Free Software
27*49cdfc7eSAndroid Build Coastguard Worker  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28*49cdfc7eSAndroid Build Coastguard Worker  * 02110-1301, USA.
29*49cdfc7eSAndroid Build Coastguard Worker  */
30*49cdfc7eSAndroid Build Coastguard Worker #include "config.h"
31*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
32*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mman.h>
33*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
34*49cdfc7eSAndroid Build Coastguard Worker #if HAVE_NUMA_H
35*49cdfc7eSAndroid Build Coastguard Worker #include <numa.h>
36*49cdfc7eSAndroid Build Coastguard Worker #endif
37*49cdfc7eSAndroid Build Coastguard Worker #if HAVE_NUMAIF_H
38*49cdfc7eSAndroid Build Coastguard Worker #include <numaif.h>
39*49cdfc7eSAndroid Build Coastguard Worker #endif
40*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
41*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
42*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
43*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
44*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
45*49cdfc7eSAndroid Build Coastguard Worker #include "test.h"
46*49cdfc7eSAndroid Build Coastguard Worker #include "safe_macros.h"
47*49cdfc7eSAndroid Build Coastguard Worker #include "numa_helper.h"
48*49cdfc7eSAndroid Build Coastguard Worker 
49*49cdfc7eSAndroid Build Coastguard Worker char *TCID = "vma02";
50*49cdfc7eSAndroid Build Coastguard Worker int TST_TOTAL = 1;
51*49cdfc7eSAndroid Build Coastguard Worker 
52*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_NUMA_V2
53*49cdfc7eSAndroid Build Coastguard Worker 
54*49cdfc7eSAndroid Build Coastguard Worker static unsigned long pagesize;
55*49cdfc7eSAndroid Build Coastguard Worker static int opt_node;
56*49cdfc7eSAndroid Build Coastguard Worker static char *opt_nodestr;
57*49cdfc7eSAndroid Build Coastguard Worker static option_t options[] = {
58*49cdfc7eSAndroid Build Coastguard Worker 	{"n:", &opt_node, &opt_nodestr},
59*49cdfc7eSAndroid Build Coastguard Worker 	{NULL, NULL, NULL}
60*49cdfc7eSAndroid Build Coastguard Worker };
61*49cdfc7eSAndroid Build Coastguard Worker 
62*49cdfc7eSAndroid Build Coastguard Worker static void usage(void);
63*49cdfc7eSAndroid Build Coastguard Worker 
main(int argc,char ** argv)64*49cdfc7eSAndroid Build Coastguard Worker int main(int argc, char **argv)
65*49cdfc7eSAndroid Build Coastguard Worker {
66*49cdfc7eSAndroid Build Coastguard Worker 	FILE *fp;
67*49cdfc7eSAndroid Build Coastguard Worker 	void *addr, *start, *end, *lastend;
68*49cdfc7eSAndroid Build Coastguard Worker 	int node, err, lc;
69*49cdfc7eSAndroid Build Coastguard Worker 	char buf[BUFSIZ];
70*49cdfc7eSAndroid Build Coastguard Worker 	struct bitmask *nmask = numa_allocate_nodemask();
71*49cdfc7eSAndroid Build Coastguard Worker 
72*49cdfc7eSAndroid Build Coastguard Worker 	pagesize = getpagesize();
73*49cdfc7eSAndroid Build Coastguard Worker 	tst_parse_opts(argc, argv, options, usage);
74*49cdfc7eSAndroid Build Coastguard Worker 
75*49cdfc7eSAndroid Build Coastguard Worker 	if (opt_node) {
76*49cdfc7eSAndroid Build Coastguard Worker 		node = SAFE_STRTOL(NULL, opt_nodestr, 1, LONG_MAX);
77*49cdfc7eSAndroid Build Coastguard Worker 	} else {
78*49cdfc7eSAndroid Build Coastguard Worker 		err = get_allowed_nodes(NH_MEMS | NH_MEMS, 1, &node);
79*49cdfc7eSAndroid Build Coastguard Worker 		if (err == -3)
80*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TCONF, NULL, "requires at least one node.");
81*49cdfc7eSAndroid Build Coastguard Worker 		else if (err < 0)
82*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TBROK | TERRNO, NULL, "get_allowed_nodes");
83*49cdfc7eSAndroid Build Coastguard Worker 	}
84*49cdfc7eSAndroid Build Coastguard Worker 	numa_bitmask_setbit(nmask, node);
85*49cdfc7eSAndroid Build Coastguard Worker 
86*49cdfc7eSAndroid Build Coastguard Worker 	for (lc = 0; TEST_LOOPING(lc); lc++) {
87*49cdfc7eSAndroid Build Coastguard Worker 		tst_count = 0;
88*49cdfc7eSAndroid Build Coastguard Worker 		addr = mmap(NULL, pagesize * 3, PROT_WRITE,
89*49cdfc7eSAndroid Build Coastguard Worker 			    MAP_ANON | MAP_PRIVATE, 0, 0);
90*49cdfc7eSAndroid Build Coastguard Worker 		if (addr == MAP_FAILED)
91*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TBROK | TERRNO, NULL, "mmap");
92*49cdfc7eSAndroid Build Coastguard Worker 
93*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TINFO, "pid = %d addr = %p", getpid(), addr);
94*49cdfc7eSAndroid Build Coastguard Worker 		/* make page populate */
95*49cdfc7eSAndroid Build Coastguard Worker 		memset(addr, 0, pagesize * 3);
96*49cdfc7eSAndroid Build Coastguard Worker 
97*49cdfc7eSAndroid Build Coastguard Worker 		/* first mbind */
98*49cdfc7eSAndroid Build Coastguard Worker 		err = mbind(addr + pagesize, pagesize, MPOL_BIND, nmask->maskp,
99*49cdfc7eSAndroid Build Coastguard Worker 			    nmask->size, MPOL_MF_MOVE_ALL);
100*49cdfc7eSAndroid Build Coastguard Worker 		if (err != 0) {
101*49cdfc7eSAndroid Build Coastguard Worker 			if (errno != ENOSYS)
102*49cdfc7eSAndroid Build Coastguard Worker 				tst_brkm(TBROK | TERRNO, NULL, "mbind1");
103*49cdfc7eSAndroid Build Coastguard Worker 			else
104*49cdfc7eSAndroid Build Coastguard Worker 				tst_brkm(TCONF, NULL,
105*49cdfc7eSAndroid Build Coastguard Worker 					 "mbind syscall not implemented on this system.");
106*49cdfc7eSAndroid Build Coastguard Worker 		}
107*49cdfc7eSAndroid Build Coastguard Worker 
108*49cdfc7eSAndroid Build Coastguard Worker 		/* second mbind */
109*49cdfc7eSAndroid Build Coastguard Worker 		err = mbind(addr, pagesize * 3, MPOL_DEFAULT, NULL, 0, 0);
110*49cdfc7eSAndroid Build Coastguard Worker 		if (err != 0)
111*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TBROK | TERRNO, NULL, "mbind2");
112*49cdfc7eSAndroid Build Coastguard Worker 
113*49cdfc7eSAndroid Build Coastguard Worker 		/* /proc/self/maps in the form of
114*49cdfc7eSAndroid Build Coastguard Worker 		   "00400000-00406000 r-xp 00000000". */
115*49cdfc7eSAndroid Build Coastguard Worker 		fp = fopen("/proc/self/maps", "r");
116*49cdfc7eSAndroid Build Coastguard Worker 		if (fp == NULL)
117*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TBROK | TERRNO, NULL, "fopen");
118*49cdfc7eSAndroid Build Coastguard Worker 
119*49cdfc7eSAndroid Build Coastguard Worker 		while (fgets(buf, BUFSIZ, fp) != NULL) {
120*49cdfc7eSAndroid Build Coastguard Worker 			if (sscanf(buf, "%p-%p ", &start, &end) != 2)
121*49cdfc7eSAndroid Build Coastguard Worker 				continue;
122*49cdfc7eSAndroid Build Coastguard Worker 
123*49cdfc7eSAndroid Build Coastguard Worker 			if (start == addr) {
124*49cdfc7eSAndroid Build Coastguard Worker 				tst_resm(TINFO, "start = %p, end = %p",
125*49cdfc7eSAndroid Build Coastguard Worker 					 start, end);
126*49cdfc7eSAndroid Build Coastguard Worker 				if (end == addr + pagesize * 3) {
127*49cdfc7eSAndroid Build Coastguard Worker 					tst_resm(TPASS, "only 1 VMA.");
128*49cdfc7eSAndroid Build Coastguard Worker 					break;
129*49cdfc7eSAndroid Build Coastguard Worker 				}
130*49cdfc7eSAndroid Build Coastguard Worker 
131*49cdfc7eSAndroid Build Coastguard Worker 				lastend = end;
132*49cdfc7eSAndroid Build Coastguard Worker 				while (fgets(buf, BUFSIZ, fp) != NULL) {
133*49cdfc7eSAndroid Build Coastguard Worker 					/* No more VMAs, break */
134*49cdfc7eSAndroid Build Coastguard Worker 					if (sscanf(buf, "%p-%p ", &start,
135*49cdfc7eSAndroid Build Coastguard Worker 						   &end) != 2)
136*49cdfc7eSAndroid Build Coastguard Worker 						break;
137*49cdfc7eSAndroid Build Coastguard Worker 					tst_resm(TINFO, "start = %p, end = %p",
138*49cdfc7eSAndroid Build Coastguard Worker 						 start, end);
139*49cdfc7eSAndroid Build Coastguard Worker 
140*49cdfc7eSAndroid Build Coastguard Worker 					/* more VMAs found */
141*49cdfc7eSAndroid Build Coastguard Worker 					if (start == lastend)
142*49cdfc7eSAndroid Build Coastguard Worker 						lastend = end;
143*49cdfc7eSAndroid Build Coastguard Worker 					if (end == addr + pagesize * 3) {
144*49cdfc7eSAndroid Build Coastguard Worker 						tst_resm(TFAIL,
145*49cdfc7eSAndroid Build Coastguard Worker 							 ">1 unmerged VMAs.");
146*49cdfc7eSAndroid Build Coastguard Worker 						break;
147*49cdfc7eSAndroid Build Coastguard Worker 					}
148*49cdfc7eSAndroid Build Coastguard Worker 				}
149*49cdfc7eSAndroid Build Coastguard Worker 				if (end != addr + pagesize * 3)
150*49cdfc7eSAndroid Build Coastguard Worker 					tst_resm(TFAIL, "no matched VMAs.");
151*49cdfc7eSAndroid Build Coastguard Worker 				break;
152*49cdfc7eSAndroid Build Coastguard Worker 			}
153*49cdfc7eSAndroid Build Coastguard Worker 		}
154*49cdfc7eSAndroid Build Coastguard Worker 		fclose(fp);
155*49cdfc7eSAndroid Build Coastguard Worker 		if (munmap(addr, pagesize * 3) == -1)
156*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TWARN | TERRNO, NULL, "munmap");
157*49cdfc7eSAndroid Build Coastguard Worker 	}
158*49cdfc7eSAndroid Build Coastguard Worker 	tst_exit();
159*49cdfc7eSAndroid Build Coastguard Worker }
160*49cdfc7eSAndroid Build Coastguard Worker 
usage(void)161*49cdfc7eSAndroid Build Coastguard Worker void usage(void)
162*49cdfc7eSAndroid Build Coastguard Worker {
163*49cdfc7eSAndroid Build Coastguard Worker 	printf("  -n      Number of NUMA nodes\n");
164*49cdfc7eSAndroid Build Coastguard Worker }
165*49cdfc7eSAndroid Build Coastguard Worker 
166*49cdfc7eSAndroid Build Coastguard Worker #else
main(void)167*49cdfc7eSAndroid Build Coastguard Worker int main(void)
168*49cdfc7eSAndroid Build Coastguard Worker {
169*49cdfc7eSAndroid Build Coastguard Worker 	tst_brkm(TCONF, NULL, NUMA_ERROR_MSG);
170*49cdfc7eSAndroid Build Coastguard Worker }
171*49cdfc7eSAndroid Build Coastguard Worker #endif
172