1 1.5 christos /* $NetBSD: t_extent.c,v 1.5 2017/01/13 21:30:41 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.5 christos __RCSID("$NetBSD: t_extent.c,v 1.5 2017/01/13 21:30:41 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.5 christos #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.4 para start, end, 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