t_extent.c revision 1.3 1 1.3 christos /* $NetBSD: t_extent.c,v 1.3 2011/06/11 18:03:17 christos Exp $ */
2 1.1 jmmv
3 1.1 jmmv /*-
4 1.1 jmmv * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 1.1 jmmv * All rights reserved.
6 1.1 jmmv *
7 1.1 jmmv * Redistribution and use in source and binary forms, with or without
8 1.1 jmmv * modification, are permitted provided that the following conditions
9 1.1 jmmv * are met:
10 1.1 jmmv * 1. Redistributions of source code must retain the above copyright
11 1.1 jmmv * notice, this list of conditions and the following disclaimer.
12 1.1 jmmv * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 jmmv * notice, this list of conditions and the following disclaimer in the
14 1.1 jmmv * documentation and/or other materials provided with the distribution.
15 1.1 jmmv *
16 1.1 jmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 1.1 jmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 1.1 jmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.1 jmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 1.1 jmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 1.1 jmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 1.1 jmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.1 jmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 1.1 jmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 1.1 jmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 1.1 jmmv * POSSIBILITY OF SUCH DAMAGE.
27 1.1 jmmv */
28 1.1 jmmv
29 1.1 jmmv #include <sys/cdefs.h>
30 1.1 jmmv __COPYRIGHT("@(#) Copyright (c) 2008\
31 1.1 jmmv The NetBSD Foundation, inc. All rights reserved.");
32 1.3 christos __RCSID("$NetBSD: t_extent.c,v 1.3 2011/06/11 18:03:17 christos Exp $");
33 1.1 jmmv
34 1.1 jmmv #include <sys/types.h>
35 1.1 jmmv #include <sys/queue.h>
36 1.1 jmmv #include <sys/extent.h>
37 1.1 jmmv
38 1.1 jmmv #include <stdio.h>
39 1.1 jmmv #include <stdlib.h>
40 1.1 jmmv #include <string.h>
41 1.1 jmmv
42 1.1 jmmv #include <atf-c.h>
43 1.1 jmmv
44 1.1 jmmv #include "../h_macros.h"
45 1.1 jmmv
46 1.1 jmmv static int ret;
47 1.1 jmmv static struct extent *ex;
48 1.1 jmmv
49 1.1 jmmv #define h_create(name, start, end, flags) \
50 1.1 jmmv ATF_REQUIRE((ex = extent_create(name, \
51 1.1 jmmv start, end, 0, 0, 0, flags)) != NULL);
52 1.1 jmmv
53 1.1 jmmv #define h_alloc_region(start, size) \
54 1.1 jmmv ATF_REQUIRE_EQ_MSG(ret = extent_alloc_region(ex, \
55 1.1 jmmv start, size, 0), 0, "%s", strerror(ret));
56 1.1 jmmv
57 1.1 jmmv #define h_free(start, size) \
58 1.1 jmmv ATF_REQUIRE_EQ_MSG(ret = extent_free(ex, \
59 1.1 jmmv start, size, 0), 0, "%s", strerror(ret));
60 1.1 jmmv
61 1.1 jmmv static void
62 1.1 jmmv h_alloc_subregion(u_long substart, u_long subend, u_long size,
63 1.1 jmmv u_long alignment, u_long boundary, int expret, u_long expres)
64 1.1 jmmv {
65 1.1 jmmv u_long result;
66 1.1 jmmv
67 1.1 jmmv #define FAIL(fmt, ...) \
68 1.1 jmmv atf_tc_fail("extent_alloc_subregion1(ex, %#lx, %#lx, %#lx, %#lx, 0, " \
69 1.1 jmmv "%#lx, 0, &result): " fmt, substart, subend, size, alignment, \
70 1.1 jmmv boundary, ##__VA_ARGS__)
71 1.1 jmmv
72 1.1 jmmv ret = extent_alloc_subregion1(ex, substart, subend, size,
73 1.1 jmmv alignment, 0, boundary, 0, &result);
74 1.1 jmmv
75 1.1 jmmv if (ret != expret)
76 1.1 jmmv FAIL("%s", strerror(errno));
77 1.1 jmmv
78 1.1 jmmv if (expret == 0 && result != expres)
79 1.1 jmmv FAIL("result should be: %#lx, got: %#lx", expres, result);
80 1.1 jmmv #undef FAIL
81 1.1 jmmv }
82 1.1 jmmv
83 1.1 jmmv static void
84 1.1 jmmv h_require(const char *name, u_long start,
85 1.3 christos u_long end, int flags, const char *exp)
86 1.1 jmmv {
87 1.1 jmmv char buf[4096];
88 1.1 jmmv struct extent_region *rp;
89 1.1 jmmv int n = 0;
90 1.1 jmmv
91 1.1 jmmv ATF_REQUIRE_STREQ_MSG(ex->ex_name, name,
92 1.1 jmmv "expected: \"%s\", got: \"%s\"", name, ex->ex_name);
93 1.1 jmmv ATF_REQUIRE_EQ_MSG(ex->ex_start, start,
94 1.1 jmmv "expected: %#lx, got: %#lx", start, ex->ex_start);
95 1.1 jmmv ATF_REQUIRE_EQ_MSG(ex->ex_end, end,
96 1.1 jmmv "expected: %#lx, got: %#lx", end, ex->ex_end);
97 1.1 jmmv ATF_REQUIRE_EQ_MSG(ex->ex_flags, flags,
98 1.3 christos "expected: %#x, got: %#x", flags, ex->ex_flags);
99 1.1 jmmv
100 1.1 jmmv (void)memset(buf, 0, sizeof(buf));
101 1.1 jmmv LIST_FOREACH(rp, &ex->ex_regions, er_link)
102 1.1 jmmv n += snprintf(buf + n, sizeof(buf) - n,
103 1.1 jmmv "0x%lx - 0x%lx\n", rp->er_start, rp->er_end);
104 1.1 jmmv
105 1.1 jmmv if (strcmp(buf, exp) == 0)
106 1.1 jmmv return;
107 1.1 jmmv
108 1.1 jmmv printf("Incorrect extent map\n");
109 1.1 jmmv printf("Expected:\n%s\n", exp);
110 1.1 jmmv printf("Got:\n%s\n", buf);
111 1.1 jmmv atf_tc_fail("incorrect extent map");
112 1.1 jmmv }
113 1.1 jmmv
114 1.1 jmmv ATF_TC(coalesce);
115 1.1 jmmv ATF_TC_HEAD(coalesce, tc)
116 1.1 jmmv {
117 1.1 jmmv atf_tc_set_md_var(tc, "descr", "Checks coalescing of regions");
118 1.1 jmmv }
119 1.1 jmmv ATF_TC_BODY(coalesce, tc)
120 1.1 jmmv {
121 1.1 jmmv h_create("test1", 0, 0x4f, 0);
122 1.1 jmmv
123 1.1 jmmv h_alloc_region(0x00, 0x10);
124 1.1 jmmv h_alloc_region(0x20, 0x10);
125 1.1 jmmv h_alloc_region(0x40, 0x10);
126 1.1 jmmv h_alloc_region(0x10, 0x10);
127 1.1 jmmv h_alloc_subregion(0, 0x4f, 0x10, EX_NOALIGN, EX_NOBOUNDARY, 0, 0x30);
128 1.1 jmmv
129 1.1 jmmv h_require("test1", 0x00, 0x4f, 0x00,
130 1.1 jmmv "0x0 - 0x4f\n");
131 1.1 jmmv
132 1.1 jmmv extent_destroy(ex);
133 1.1 jmmv }
134 1.1 jmmv
135 1.1 jmmv ATF_TC(subregion1);
136 1.1 jmmv ATF_TC_HEAD(subregion1, tc)
137 1.1 jmmv {
138 1.1 jmmv atf_tc_set_md_var(tc, "descr",
139 1.1 jmmv "Checks that subregions work (PR kern/7539)");
140 1.1 jmmv }
141 1.1 jmmv ATF_TC_BODY(subregion1, tc)
142 1.1 jmmv {
143 1.1 jmmv h_create("test2", 0, 0x2f, EX_NOCOALESCE);
144 1.1 jmmv
145 1.1 jmmv h_alloc_region(0x00, 0x10);
146 1.1 jmmv h_alloc_subregion(0x20, 0x30, 0x10, EX_NOALIGN, EX_NOBOUNDARY, 0, 0x20);
147 1.1 jmmv
148 1.1 jmmv h_require("test2", 0x00, 0x2f, 0x2,
149 1.1 jmmv "0x0 - 0xf\n"
150 1.1 jmmv "0x20 - 0x2f\n");
151 1.1 jmmv
152 1.1 jmmv extent_destroy(ex);
153 1.1 jmmv }
154 1.1 jmmv
155 1.1 jmmv ATF_TC(subregion2);
156 1.1 jmmv ATF_TC_HEAD(subregion2, tc)
157 1.1 jmmv {
158 1.1 jmmv atf_tc_set_md_var(tc, "descr",
159 1.1 jmmv "Checks that subregion allocations don't overlap with existing "
160 1.1 jmmv "ones (fixed in 1.25)");
161 1.1 jmmv }
162 1.1 jmmv ATF_TC_BODY(subregion2, tc)
163 1.1 jmmv {
164 1.1 jmmv h_create("test3", 0, 0x3f, EX_NOCOALESCE);
165 1.1 jmmv
166 1.1 jmmv h_alloc_region(0x00, 0x20);
167 1.1 jmmv h_alloc_region(0x30, 0x10);
168 1.1 jmmv h_alloc_subregion(0x10, 0x3f, 0x10,
169 1.1 jmmv EX_NOALIGN, EX_NOBOUNDARY, 0, 0x20);
170 1.1 jmmv
171 1.1 jmmv h_require("test3", 0x00, 0x3f, 0x2,
172 1.1 jmmv "0x0 - 0x1f\n"
173 1.1 jmmv "0x20 - 0x2f\n"
174 1.1 jmmv "0x30 - 0x3f\n");
175 1.1 jmmv
176 1.1 jmmv extent_destroy(ex);
177 1.1 jmmv }
178 1.1 jmmv
179 1.1 jmmv ATF_TC(bound1);
180 1.1 jmmv ATF_TC_HEAD(bound1, tc)
181 1.1 jmmv {
182 1.1 jmmv atf_tc_set_md_var(tc, "descr",
183 1.1 jmmv "Checks for overflow in boundary check, before an allocated region "
184 1.1 jmmv "(fixed in 1.32)");
185 1.1 jmmv }
186 1.1 jmmv ATF_TC_BODY(bound1, tc)
187 1.1 jmmv {
188 1.1 jmmv h_create("test4", 0xf0000000, 0xffffffff, 0);
189 1.1 jmmv
190 1.1 jmmv h_alloc_region(0xf1000000, 0x1);
191 1.1 jmmv h_alloc_subregion(0xf0000000, 0xffffffff, 0x1,
192 1.1 jmmv EX_NOALIGN, 0x20000000, 0, 0xf0000000);
193 1.1 jmmv
194 1.1 jmmv h_require("test4", 0xf0000000, 0xffffffff, 0x0,
195 1.1 jmmv "0xf0000000 - 0xf0000000\n"
196 1.1 jmmv "0xf1000000 - 0xf1000000\n");
197 1.1 jmmv
198 1.1 jmmv extent_destroy(ex);
199 1.1 jmmv }
200 1.1 jmmv
201 1.1 jmmv ATF_TC(bound2);
202 1.1 jmmv ATF_TC_HEAD(bound2, tc)
203 1.1 jmmv {
204 1.1 jmmv atf_tc_set_md_var(tc, "descr",
205 1.1 jmmv "Checks for overflow in boundary checks, before the subregion end "
206 1.1 jmmv "(fixed in 1.32)");
207 1.1 jmmv }
208 1.1 jmmv ATF_TC_BODY(bound2, tc)
209 1.1 jmmv {
210 1.1 jmmv h_create("test5", 0xf0000000, 0xffffffff, 0);
211 1.1 jmmv
212 1.1 jmmv h_alloc_subregion(0xf0000000, 0xffffffff, 0x1,
213 1.1 jmmv EX_NOALIGN, 0x20000000, 0, 0xf0000000);
214 1.1 jmmv
215 1.1 jmmv h_require("test5", 0xf0000000, 0xffffffff, 0x0,
216 1.1 jmmv "0xf0000000 - 0xf0000000\n");
217 1.1 jmmv
218 1.1 jmmv extent_destroy(ex);
219 1.1 jmmv }
220 1.1 jmmv
221 1.1 jmmv ATF_TC(bound3);
222 1.1 jmmv ATF_TC_HEAD(bound3, tc)
223 1.1 jmmv {
224 1.1 jmmv atf_tc_set_md_var(tc, "descr",
225 1.1 jmmv "Checks allocation beyond last boundary line: last two "
226 1.1 jmmv "allocations should succeed without boundary \"fixups\"");
227 1.1 jmmv }
228 1.1 jmmv ATF_TC_BODY(bound3, tc)
229 1.1 jmmv {
230 1.1 jmmv h_create("test6", 0, 11, 0);
231 1.1 jmmv
232 1.1 jmmv h_alloc_subregion(0, 11, 8, EX_NOALIGN, 8, 0, 0);
233 1.1 jmmv h_alloc_subregion(0, 11, 2, EX_NOALIGN, 8, 0, 0x8);
234 1.1 jmmv h_alloc_subregion(0, 11, 2, EX_NOALIGN, 8, 0, 0xa);
235 1.1 jmmv
236 1.1 jmmv h_require("test6", 0x0, 0xb, 0x0, "0x0 - 0xb\n");
237 1.1 jmmv
238 1.1 jmmv extent_destroy(ex);
239 1.1 jmmv }
240 1.1 jmmv
241 1.1 jmmv ATF_TC(bound4);
242 1.1 jmmv ATF_TC_HEAD(bound4, tc)
243 1.1 jmmv {
244 1.1 jmmv atf_tc_set_md_var(tc, "descr",
245 1.1 jmmv "Checks allocation beyond last boundary line: last allocation "
246 1.1 jmmv "should be bumped to the next boundary and exactly fit the "
247 1.1 jmmv "remaining space");
248 1.1 jmmv }
249 1.1 jmmv ATF_TC_BODY(bound4, tc)
250 1.1 jmmv {
251 1.1 jmmv h_create("test7", 0, 11, 0);
252 1.1 jmmv
253 1.1 jmmv h_alloc_subregion(0, 11, 7, EX_NOALIGN, 8, 0, 0);
254 1.1 jmmv h_alloc_subregion(0, 11, 4, EX_NOALIGN, 8, 0, 8);
255 1.1 jmmv
256 1.1 jmmv h_require("test7", 0x0, 0xb, 0x0,
257 1.1 jmmv "0x0 - 0x6\n"
258 1.1 jmmv "0x8 - 0xb\n");
259 1.1 jmmv
260 1.1 jmmv extent_destroy(ex);
261 1.1 jmmv }
262 1.1 jmmv
263 1.1 jmmv ATF_TC(subregion3);
264 1.1 jmmv ATF_TC_HEAD(subregion3, tc)
265 1.1 jmmv {
266 1.1 jmmv atf_tc_set_md_var(tc, "descr",
267 1.1 jmmv "Checks that we don't allocate a region pasts the end of "
268 1.1 jmmv "subregion (i.e., the second alloc_subregion should fail). "
269 1.1 jmmv "subr_extent.c prior to rev. 1.43 allocated region starting "
270 1.1 jmmv "from 0x10");
271 1.1 jmmv }
272 1.1 jmmv ATF_TC_BODY(subregion3, tc)
273 1.1 jmmv {
274 1.1 jmmv h_create("test8", 0, 0x4f, EX_NOCOALESCE);
275 1.1 jmmv
276 1.1 jmmv h_alloc_region(0x30, 0x10);
277 1.1 jmmv h_alloc_subregion(0, 0xf, 0x10, EX_NOALIGN, EX_NOBOUNDARY, 0, 0);
278 1.1 jmmv h_alloc_subregion(0, 0xf, 0x10, EX_NOALIGN, EX_NOBOUNDARY, EAGAIN, 0);
279 1.1 jmmv
280 1.1 jmmv h_require("test8", 0x0, 0x4f, 0x2,
281 1.1 jmmv "0x0 - 0xf\n"
282 1.1 jmmv "0x30 - 0x3f\n");
283 1.1 jmmv
284 1.1 jmmv extent_destroy(ex);
285 1.1 jmmv }
286 1.1 jmmv
287 1.1 jmmv ATF_TC(bound5);
288 1.1 jmmv ATF_TC_HEAD(bound5, tc)
289 1.1 jmmv {
290 1.1 jmmv atf_tc_set_md_var(tc, "descr",
291 1.1 jmmv "When allocating a region with a boundary constraint, checks "
292 1.1 jmmv "proper detection of overflaps once the candidate region has "
293 1.1 jmmv "been aligned. subr_extent.c prior 1.45 could corrupt the extent "
294 1.1 jmmv "map in this situation");
295 1.1 jmmv }
296 1.1 jmmv ATF_TC_BODY(bound5, tc)
297 1.1 jmmv {
298 1.1 jmmv h_create("test9", 0, 0x4f, 0);
299 1.1 jmmv
300 1.1 jmmv h_alloc_subregion(0, 0x10, 4, EX_NOALIGN, 0, 0, 0);
301 1.1 jmmv h_alloc_subregion(0xd, 0x20, 2, EX_NOALIGN, 0, 0, 0xd);
302 1.1 jmmv h_alloc_subregion(0, 0x4f, 8, EX_NOALIGN, 8, 0, 0x10);
303 1.1 jmmv
304 1.1 jmmv h_require("test9", 0x0, 0x4f, 0x0,
305 1.1 jmmv "0x0 - 0x3\n"
306 1.1 jmmv "0xd - 0xe\n"
307 1.1 jmmv "0x10 - 0x17\n");
308 1.1 jmmv
309 1.1 jmmv extent_destroy(ex);
310 1.1 jmmv }
311 1.1 jmmv
312 1.1 jmmv ATF_TC(free);
313 1.1 jmmv ATF_TC_HEAD(free, tc)
314 1.1 jmmv {
315 1.1 jmmv atf_tc_set_md_var(tc, "descr", "Checks extent_free()");
316 1.1 jmmv }
317 1.1 jmmv ATF_TC_BODY(free, tc)
318 1.1 jmmv {
319 1.1 jmmv h_create("test10", 0xc0002000, 0xffffe000, EX_BOUNDZERO);
320 1.1 jmmv
321 1.1 jmmv h_alloc_subregion(0xc0002000, 0xffffe000, 0x2000,
322 1.1 jmmv 0x10000, 0x10000, 0, 0xc0010000);
323 1.1 jmmv h_alloc_subregion(0xc0002000, 0xffffe000, 0x2000,
324 1.1 jmmv 0x10000, 0x10000, 0, 0xc0020000);
325 1.1 jmmv
326 1.1 jmmv h_require("test10", 0xc0002000, 0xffffe000, 0x0,
327 1.1 jmmv "0xc0010000 - 0xc0011fff\n"
328 1.1 jmmv "0xc0020000 - 0xc0021fff\n");
329 1.1 jmmv
330 1.1 jmmv h_free(0xc0020000, 0x2000);
331 1.1 jmmv h_require("test10", 0xc0002000, 0xffffe000, 0x0,
332 1.1 jmmv "0xc0010000 - 0xc0011fff\n");
333 1.1 jmmv
334 1.1 jmmv h_alloc_subregion(0xc0002000, 0xffffe000, 0x10000,
335 1.1 jmmv 0x10000, 0x10000, 0, 0xc0022000);
336 1.1 jmmv
337 1.1 jmmv h_require("test10", 0xc0002000, 0xffffe000, 0x0,
338 1.1 jmmv "0xc0010000 - 0xc0011fff\n"
339 1.1 jmmv "0xc0022000 - 0xc0031fff\n");
340 1.1 jmmv
341 1.1 jmmv extent_destroy(ex);
342 1.1 jmmv }
343 1.1 jmmv
344 1.1 jmmv ATF_TC(subregion4);
345 1.1 jmmv ATF_TC_HEAD(subregion4, tc)
346 1.1 jmmv {
347 1.1 jmmv atf_tc_set_md_var(tc, "descr",
348 1.1 jmmv "Checks for off-by-one bug which would cause a region at the end "
349 1.1 jmmv "of the extent to be allocated multiple times (fixed in 1.51)");
350 1.1 jmmv }
351 1.1 jmmv ATF_TC_BODY(subregion4, tc)
352 1.1 jmmv {
353 1.1 jmmv h_create("test11", 0x10, 0x20, EX_NOCOALESCE);
354 1.1 jmmv
355 1.1 jmmv h_alloc_subregion(0x10, 0x13, 0x4, EX_NOALIGN, EX_NOBOUNDARY, 0, 0x10);
356 1.1 jmmv h_alloc_subregion(0x1e, 0x1f, 0x2, EX_NOALIGN, EX_NOBOUNDARY, 0, 0x1e);
357 1.1 jmmv h_alloc_subregion(0x20, 0x20, 0x1, EX_NOALIGN, EX_NOBOUNDARY, 0, 0x20);
358 1.1 jmmv h_alloc_subregion(0x20, 0x20, 0x1, EX_NOALIGN, EX_NOBOUNDARY, EAGAIN, 0);
359 1.1 jmmv h_alloc_subregion(0x10, 0x20, 0x1, EX_NOALIGN, EX_NOBOUNDARY, 0, 0x14);
360 1.1 jmmv
361 1.1 jmmv h_require("test11", 0x10, 0x20, 0x2,
362 1.1 jmmv "0x10 - 0x13\n"
363 1.1 jmmv "0x14 - 0x14\n"
364 1.1 jmmv "0x1e - 0x1f\n"
365 1.1 jmmv "0x20 - 0x20\n");
366 1.1 jmmv
367 1.1 jmmv extent_destroy(ex);
368 1.1 jmmv }
369 1.1 jmmv
370 1.1 jmmv ATF_TP_ADD_TCS(tp)
371 1.1 jmmv {
372 1.1 jmmv ATF_TP_ADD_TC(tp, coalesce);
373 1.1 jmmv ATF_TP_ADD_TC(tp, subregion1);
374 1.1 jmmv ATF_TP_ADD_TC(tp, subregion2);
375 1.1 jmmv ATF_TP_ADD_TC(tp, bound1);
376 1.1 jmmv ATF_TP_ADD_TC(tp, bound2);
377 1.1 jmmv ATF_TP_ADD_TC(tp, bound3);
378 1.1 jmmv ATF_TP_ADD_TC(tp, bound4);
379 1.1 jmmv ATF_TP_ADD_TC(tp, subregion3);
380 1.1 jmmv ATF_TP_ADD_TC(tp, bound5);
381 1.1 jmmv ATF_TP_ADD_TC(tp, free);
382 1.1 jmmv ATF_TP_ADD_TC(tp, subregion4);
383 1.1 jmmv
384 1.1 jmmv return atf_no_error();
385 1.1 jmmv }
386