blob: e612bf1d802297af94db77ce20bdf3606ecd5c9d [file] [log] [blame]
Jan Stanceke6a89db2012-11-05 12:18:33 +01001/*
2 * Copyright (C) 2012 Linux Test Project, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it
13 * is free of the rightful claim of any third person regarding
14 * infringement or the like. Any license provided herein, whether
15 * implied or otherwise, applies only to this software file. Patent
16 * licenses, if any, provided herein do not apply to combinations of
17 * this program with other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 */
24/*
25 * Test Name: mremap05
26 *
27 * Test Description:
28 * Verify that MREMAP_FIXED fails without MREMAP_MAYMOVE.
29 * Verify that MREMAP_FIXED|MREMAP_MAYMOVE fails if target address
30 * is not page aligned.
31 * Verify that MREMAP_FIXED|MREMAP_MAYMOVE fails if old range
32 * overlaps with new range.
33 * Verify that MREMAP_FIXED|MREMAP_MAYMOVE can move mapping to new address.
34 * Verify that MREMAP_FIXED|MREMAP_MAYMOVE unmaps previous mapping
35 * at the address range specified by new_address and new_size.
36 */
37
38#define _GNU_SOURCE
Cyril Hrubis123bb3d2013-01-21 16:11:26 +010039#include "config.h"
Jan Stanceke6a89db2012-11-05 12:18:33 +010040#include <sys/mman.h>
41#include <errno.h>
42#include <unistd.h>
43#include "test.h"
Jan Stanceke6a89db2012-11-05 12:18:33 +010044
45char *TCID = "mremap05";
46
Cyril Hrubis123bb3d2013-01-21 16:11:26 +010047#ifdef HAVE_MREMAP_FIXED
48
Jan Stanceke6a89db2012-11-05 12:18:33 +010049struct test_case_t {
50 char *old_address;
51 char *new_address;
Wanlong Gao354ebb42012-12-07 10:10:04 +080052 size_t old_size; /* in pages */
53 size_t new_size; /* in pages */
Jan Stanceke6a89db2012-11-05 12:18:33 +010054 int flags;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020055 const const char *msg;
Jan Stanceke6a89db2012-11-05 12:18:33 +010056 void *exp_ret;
57 int exp_errno;
58 char *ret;
Wanlong Gao354ebb42012-12-07 10:10:04 +080059 void (*setup) (struct test_case_t *);
60 void (*cleanup) (struct test_case_t *);
Jan Stanceke6a89db2012-11-05 12:18:33 +010061};
62
63static void setup(void);
64static void cleanup(void);
65static void setup0(struct test_case_t *);
66static void setup1(struct test_case_t *);
67static void setup2(struct test_case_t *);
68static void setup3(struct test_case_t *);
69static void setup4(struct test_case_t *);
70static void cleanup0(struct test_case_t *);
71static void cleanup1(struct test_case_t *);
72
73struct test_case_t tdat[] = {
74 {
Wanlong Gao354ebb42012-12-07 10:10:04 +080075 .old_size = 1,
76 .new_size = 1,
77 .flags = MREMAP_FIXED,
78 .msg = "MREMAP_FIXED requires MREMAP_MAYMOVE",
79 .exp_ret = MAP_FAILED,
80 .exp_errno = EINVAL,
81 .setup = setup0,
82 .cleanup = cleanup0},
Jan Stanceke6a89db2012-11-05 12:18:33 +010083 {
Wanlong Gao354ebb42012-12-07 10:10:04 +080084 .old_size = 1,
85 .new_size = 1,
86 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
87 .msg = "new_addr has to be page aligned",
88 .exp_ret = MAP_FAILED,
89 .exp_errno = EINVAL,
90 .setup = setup1,
91 .cleanup = cleanup0},
Jan Stanceke6a89db2012-11-05 12:18:33 +010092 {
Wanlong Gao354ebb42012-12-07 10:10:04 +080093 .old_size = 2,
94 .new_size = 1,
95 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
96 .msg = "old/new area must not overlap",
97 .exp_ret = MAP_FAILED,
98 .exp_errno = EINVAL,
99 .setup = setup2,
100 .cleanup = cleanup0},
Jan Stanceke6a89db2012-11-05 12:18:33 +0100101 {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800102 .old_size = 1,
103 .new_size = 1,
104 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
105 .msg = "mremap #1",
106 .setup = setup3,
107 .cleanup = cleanup0},
Jan Stanceke6a89db2012-11-05 12:18:33 +0100108 {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800109 .old_size = 1,
110 .new_size = 1,
111 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
112 .msg = "mremap #2",
113 .setup = setup4,
114 .cleanup = cleanup1},
Jan Stanceke6a89db2012-11-05 12:18:33 +0100115};
116
117static int pagesize;
118static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
119
120static void free_test_area(void *p, int size)
121{
122 if (munmap(p, size) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800123 tst_brkm(TBROK | TERRNO, cleanup, "free_test_area munmap");
Jan Stanceke6a89db2012-11-05 12:18:33 +0100124}
125
126static void *get_test_area(int size, int free_area)
127{
128 void *p;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800129 p = mmap(NULL, size, PROT_READ | PROT_WRITE,
130 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
Jan Stanceke6a89db2012-11-05 12:18:33 +0100131 if (p == MAP_FAILED)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800132 tst_brkm(TBROK | TERRNO, cleanup, "get_test_area mmap");
Jan Stanceke6a89db2012-11-05 12:18:33 +0100133 if (free_area)
134 free_test_area(p, size);
135 return p;
136}
137
138static void test_mremap(struct test_case_t *t)
139{
140 t->ret = mremap(t->old_address, t->old_size, t->new_size, t->flags,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800141 t->new_address);
Jan Stanceke6a89db2012-11-05 12:18:33 +0100142
143 if (t->ret == t->exp_ret) {
144 if (t->ret != MAP_FAILED) {
145 tst_resm(TPASS, "%s", t->msg);
146 if (*(t->ret) == 0x1)
147 tst_resm(TPASS, "%s value OK", t->msg);
148 else
149 tst_resm(TPASS, "%s value failed", t->msg);
150 } else {
151 if (errno == t->exp_errno)
152 tst_resm(TPASS, "%s", t->msg);
153 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800154 tst_resm(TFAIL | TERRNO, "%s", t->msg);
Jan Stanceke6a89db2012-11-05 12:18:33 +0100155 }
156 } else {
157 tst_resm(TFAIL, "%s ret: %p, expected: %p", t->msg,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800158 t->ret, t->exp_ret);
Jan Stanceke6a89db2012-11-05 12:18:33 +0100159 }
160}
161
162static void setup0(struct test_case_t *t)
163{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800164 t->old_address = get_test_area(t->old_size * pagesize, 0);
165 t->new_address = get_test_area(t->new_size * pagesize, 1);
Jan Stanceke6a89db2012-11-05 12:18:33 +0100166}
167
168static void setup1(struct test_case_t *t)
169{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800170 t->old_address = get_test_area(t->old_size * pagesize, 0);
171 t->new_address = get_test_area((t->new_size + 1) * pagesize, 1) + 1;
Jan Stanceke6a89db2012-11-05 12:18:33 +0100172}
173
174static void setup2(struct test_case_t *t)
175{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800176 t->old_address = get_test_area(t->old_size * pagesize, 0);
Jan Stanceke6a89db2012-11-05 12:18:33 +0100177 t->new_address = t->old_address;
178}
179
180static void setup3(struct test_case_t *t)
181{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800182 t->old_address = get_test_area(t->old_size * pagesize, 0);
183 t->new_address = get_test_area(t->new_size * pagesize, 1);
Jan Stanceke6a89db2012-11-05 12:18:33 +0100184 t->exp_ret = t->new_address;
185 *(t->old_address) = 0x1;
186}
187
188static void setup4(struct test_case_t *t)
189{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800190 t->old_address = get_test_area(t->old_size * pagesize, 0);
191 t->new_address = get_test_area(t->new_size * pagesize, 0);
Jan Stanceke6a89db2012-11-05 12:18:33 +0100192 t->exp_ret = t->new_address;
193 *(t->old_address) = 0x1;
194 *(t->new_address) = 0x2;
195}
196
197static void cleanup0(struct test_case_t *t)
198{
199 if (t->ret == MAP_FAILED)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800200 free_test_area(t->old_address, t->old_size * pagesize);
Jan Stanceke6a89db2012-11-05 12:18:33 +0100201 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800202 free_test_area(t->ret, t->new_size * pagesize);
Jan Stanceke6a89db2012-11-05 12:18:33 +0100203}
204
205static void cleanup1(struct test_case_t *t)
206{
207 if (t->ret == MAP_FAILED) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800208 free_test_area(t->old_address, t->old_size * pagesize);
209 free_test_area(t->new_address, t->new_size * pagesize);
Jan Stanceke6a89db2012-11-05 12:18:33 +0100210 } else {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800211 free_test_area(t->ret, t->new_size * pagesize);
Jan Stanceke6a89db2012-11-05 12:18:33 +0100212 }
213}
214
215int main(int ac, char **av)
216{
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200217 const char *msg;
Jan Stanceke6a89db2012-11-05 12:18:33 +0100218 int lc, testno;
219
220 msg = parse_opts(ac, av, NULL, NULL);
221 if (msg != NULL)
222 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
223
224 setup();
225 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800226 tst_count = 0;
Jan Stanceke6a89db2012-11-05 12:18:33 +0100227 for (testno = 0; testno < TST_TOTAL; testno++) {
228 tdat[testno].setup(&tdat[testno]);
229 test_mremap(&tdat[testno]);
230 tdat[testno].cleanup(&tdat[testno]);
231 }
232 }
233 cleanup();
234 tst_exit();
235}
236
237static void setup(void)
238{
239 pagesize = getpagesize();
240}
241
242static void cleanup(void)
243{
Jan Stanceke6a89db2012-11-05 12:18:33 +0100244}
Cyril Hrubis123bb3d2013-01-21 16:11:26 +0100245
246#else
247
248int main(void)
249{
250 tst_brkm(TCONF, NULL, "MREMAP_FIXED not present in <sys/mman.h>");
251}
252
253#endif /* HAVE_MREMAP_FIXED */