blob: eb8cc6ab51388aead14402aa0f0705c1c1c49b8f [file] [log] [blame]
Garrett Cooper05de7412010-12-08 00:40:35 -08001/*
2 * This is a reproducer from mainline commit
3 * 9d8cebd4bcd7c3878462fdfda34bbcdeb4df7ef4:
4 *
5 * "Strangely, current mbind() doesn't merge vma with neighbor vma
6 * although it's possible. Unfortunately, many vma can reduce
7 * performance..."
8 *
9 * Copyright (C) 2010 Red Hat, Inc.
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General Public
12 * License as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it would be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 *
18 * Further, this software is distributed without any warranty that it
19 * is free of the rightful claim of any third person regarding
20 * infringement or the like. Any license provided herein, whether
21 * implied or otherwise, applies only to this software file. Patent
22 * licenses, if any, provided herein do not apply to combinations of
23 * this program with other software, or any other product whatsoever.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28 * 02110-1301, USA.
29 */
Caspar Zhang79667fa2012-03-12 14:41:46 +080030#include "config.h"
31#include <sys/types.h>
32#include <sys/mman.h>
33#include <errno.h>
34#if HAVE_NUMA_H
35#include <numa.h>
36#endif
37#if HAVE_NUMAIF_H
38#include <numaif.h>
39#endif
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <unistd.h>
Garrett Cooper05de7412010-12-08 00:40:35 -080044#include "test.h"
Caspar Zhanga98ac192012-08-09 14:15:41 +080045#include "safe_macros.h"
46#include "numa_helper.h"
Garrett Cooper05de7412010-12-08 00:40:35 -080047
Caspar Zhangecc0bf82011-08-01 09:26:09 +080048char *TCID = "vma02";
Garrett Cooper05de7412010-12-08 00:40:35 -080049int TST_TOTAL = 1;
Garrett Cooper05de7412010-12-08 00:40:35 -080050
51#if HAVE_NUMA_H && HAVE_LINUX_MEMPOLICY_H && HAVE_NUMAIF_H \
52 && HAVE_MPOL_CONSTANTS
Garrett Cooper7b426ce2011-04-21 23:36:26 -070053#if defined(LIBNUMA_API_VERSION) && LIBNUMA_API_VERSION == 2
Garrett Cooper05de7412010-12-08 00:40:35 -080054static unsigned long pagesize;
55static int opt_node;
56static char *opt_nodestr;
57static option_t options[] = {
Wanlong Gao354ebb42012-12-07 10:10:04 +080058 {"n:", &opt_node, &opt_nodestr},
59 {NULL, NULL, NULL}
Garrett Cooper05de7412010-12-08 00:40:35 -080060};
61
62static void usage(void);
63
Caspar Zhang79667fa2012-03-12 14:41:46 +080064int main(int argc, char **argv)
Garrett Cooper05de7412010-12-08 00:40:35 -080065{
66 FILE *fp;
Caspar Zhang6f864d92011-08-01 09:26:08 +080067 void *addr, *start, *end, *lastend;
Garrett Cooper05de7412010-12-08 00:40:35 -080068 int node, err, lc;
Caspar Zhang6f864d92011-08-01 09:26:08 +080069 char buf[BUFSIZ];
Garrett Cooper05de7412010-12-08 00:40:35 -080070 struct bitmask *nmask = numa_allocate_nodemask();
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020071 const char *msg;
Garrett Cooper05de7412010-12-08 00:40:35 -080072
73 pagesize = getpagesize();
74 msg = parse_opts(argc, argv, options, usage);
75 if (msg != NULL)
Garrett Cooper53740502010-12-16 00:04:01 -080076 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Caspar Zhanga98ac192012-08-09 14:15:41 +080077
Garrett Cooper05de7412010-12-08 00:40:35 -080078 if (opt_node) {
Caspar Zhanga98ac192012-08-09 14:15:41 +080079 node = SAFE_STRTOL(NULL, opt_nodestr, 1, LONG_MAX);
80 } else {
Wanlong Gao354ebb42012-12-07 10:10:04 +080081 err = get_allowed_nodes(NH_MEMS | NH_MEMS, 1, &node);
Caspar Zhanga98ac192012-08-09 14:15:41 +080082 if (err == -3)
83 tst_brkm(TCONF, NULL, "requires at least one node.");
84 else if (err < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +080085 tst_brkm(TBROK | TERRNO, NULL, "get_allowed_nodes");
Caspar Zhanga98ac192012-08-09 14:15:41 +080086 }
87 numa_bitmask_setbit(nmask, node);
Garrett Cooper05de7412010-12-08 00:40:35 -080088
89 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +080090 tst_count = 0;
Wanlong Gao354ebb42012-12-07 10:10:04 +080091 addr = mmap(NULL, pagesize * 3, PROT_WRITE,
92 MAP_ANON | MAP_PRIVATE, 0, 0);
Garrett Cooper05de7412010-12-08 00:40:35 -080093 if (addr == MAP_FAILED)
Wanlong Gao354ebb42012-12-07 10:10:04 +080094 tst_brkm(TBROK | TERRNO, NULL, "mmap");
Garrett Cooper05de7412010-12-08 00:40:35 -080095
96 tst_resm(TINFO, "pid = %d addr = %p", getpid(), addr);
97 /* make page populate */
Wanlong Gao354ebb42012-12-07 10:10:04 +080098 memset(addr, 0, pagesize * 3);
Garrett Cooper05de7412010-12-08 00:40:35 -080099
100 /* first mbind */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800101 err = mbind(addr + pagesize, pagesize, MPOL_BIND, nmask->maskp,
102 nmask->size, MPOL_MF_MOVE_ALL);
Garrett Cooper14d49602011-04-11 23:47:45 -0700103 if (err != 0) {
104 if (errno != ENOSYS)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800105 tst_brkm(TBROK | TERRNO, NULL, "mbind1");
Garrett Cooper14d49602011-04-11 23:47:45 -0700106 else
107 tst_brkm(TCONF, NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800108 "mbind syscall not implemented on this system.");
Garrett Cooper14d49602011-04-11 23:47:45 -0700109 }
Garrett Cooper05de7412010-12-08 00:40:35 -0800110
111 /* second mbind */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800112 err = mbind(addr, pagesize * 3, MPOL_DEFAULT, NULL, 0, 0);
Garrett Cooper05de7412010-12-08 00:40:35 -0800113 if (err != 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800114 tst_brkm(TBROK | TERRNO, NULL, "mbind2");
Garrett Cooper05de7412010-12-08 00:40:35 -0800115
116 /* /proc/self/maps in the form of
117 "00400000-00406000 r-xp 00000000". */
Garrett Cooper05de7412010-12-08 00:40:35 -0800118 fp = fopen("/proc/self/maps", "r");
119 if (fp == NULL)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800120 tst_brkm(TBROK | TERRNO, NULL, "fopen");
Garrett Cooper05de7412010-12-08 00:40:35 -0800121
122 while (fgets(buf, BUFSIZ, fp) != NULL) {
Caspar Zhang6f864d92011-08-01 09:26:08 +0800123 if (sscanf(buf, "%p-%p ", &start, &end) != 2)
Garrett Cooper05de7412010-12-08 00:40:35 -0800124 continue;
Caspar Zhang6f864d92011-08-01 09:26:08 +0800125
126 if (start == addr) {
127 tst_resm(TINFO, "start = %p, end = %p",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800128 start, end);
129 if (end == addr + pagesize * 3) {
Caspar Zhang6f864d92011-08-01 09:26:08 +0800130 tst_resm(TPASS, "only 1 VMA.");
131 break;
132 }
133
134 lastend = end;
135 while (fgets(buf, BUFSIZ, fp) != NULL) {
136 /* No more VMAs, break */
137 if (sscanf(buf, "%p-%p ", &start,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800138 &end) != 2)
Caspar Zhang6f864d92011-08-01 09:26:08 +0800139 break;
140 tst_resm(TINFO, "start = %p, end = %p",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800141 start, end);
Caspar Zhang6f864d92011-08-01 09:26:08 +0800142
143 /* more VMAs found */
144 if (start == lastend)
145 lastend = end;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800146 if (end == addr + pagesize * 3) {
Caspar Zhang6f864d92011-08-01 09:26:08 +0800147 tst_resm(TFAIL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800148 ">1 unmerged VMAs.");
Caspar Zhang6f864d92011-08-01 09:26:08 +0800149 break;
150 }
151 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800152 if (end != addr + pagesize * 3)
Caspar Zhang6f864d92011-08-01 09:26:08 +0800153 tst_resm(TFAIL, "no matched VMAs.");
154 break;
155 }
Garrett Cooper05de7412010-12-08 00:40:35 -0800156 }
157 fclose(fp);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800158 if (munmap(addr, pagesize * 3) == -1)
159 tst_brkm(TWARN | TERRNO, NULL, "munmap");
Garrett Cooper05de7412010-12-08 00:40:35 -0800160 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800161 tst_exit();
Garrett Cooper05de7412010-12-08 00:40:35 -0800162}
163
164void usage(void)
165{
166 printf(" -n Number of NUMA nodes\n");
167}
Garrett Cooper7b426ce2011-04-21 23:36:26 -0700168#else /* libnuma v1 */
Caspar Zhang79667fa2012-03-12 14:41:46 +0800169int main(void)
170{
Garrett Cooper203573c2011-05-04 09:55:59 -0700171 tst_brkm(TCONF, NULL, "XXX: test is only supported on libnuma v2.");
Garrett Cooper7b426ce2011-04-21 23:36:26 -0700172}
173#endif
Garrett Cooper05de7412010-12-08 00:40:35 -0800174#else /* no NUMA */
Caspar Zhang79667fa2012-03-12 14:41:46 +0800175int main(void)
176{
Garrett Cooper203573c2011-05-04 09:55:59 -0700177 tst_brkm(TCONF, NULL, "no NUMA development packages installed.");
Garrett Cooper05de7412010-12-08 00:40:35 -0800178}
Garrett Cooper14d49602011-04-11 23:47:45 -0700179#endif