1 /* $OpenBSD: subr_extent.c,v 1.49 2014/01/21 01:48:44 tedu Exp $ */ 2 /* $NetBSD: subr_extent.c,v 1.7 1996/11/21 18:46:34 cgd Exp $ */ 3 4 /*- 5 * Copyright (c) 1996, 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jason R. Thorpe and Matthias Drochner. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * General purpose extent manager. 35 */ 36 37 #ifdef _KERNEL 38 #include <sys/param.h> 39 #include <sys/extent.h> 40 #include <sys/malloc.h> 41 #include <sys/time.h> 42 #include <sys/systm.h> 43 #include <sys/proc.h> 44 #include <sys/queue.h> 45 #include <sys/pool.h> 46 #include <ddb/db_output.h> 47 #else 48 /* 49 * user-land definitions, so it can fit into a testing harness. 50 */ 51 #include <sys/param.h> 52 #include <sys/pool.h> 53 #include <sys/extent.h> 54 #include <sys/queue.h> 55 #include <errno.h> 56 #include <stdlib.h> 57 #include <stdio.h> 58 #include <string.h> 59 60 #define malloc(s, t, flags) malloc(s) 61 #define free(p, t) free(p) 62 #define tsleep(chan, pri, str, timo) (EWOULDBLOCK) 63 #define wakeup(chan) ((void)0) 64 #define pool_get(pool, flags) malloc((pool)->pr_size, 0, 0) 65 #define pool_init(a, b, c, d, e, f, g) (a)->pr_size = (b) 66 #define pool_setipl(pool, ipl) /* nothing */ 67 #define pool_put(pool, rp) free((rp), 0) 68 #define panic printf 69 #endif 70 71 #if defined(DIAGNOSTIC) || defined(DDB) 72 void extent_print1(struct extent *, int (*)(const char *, ...) 73 __attribute__((__format__(__kprintf__,1,2)))); 74 #endif 75 76 static void extent_insert_and_optimize(struct extent *, u_long, u_long, 77 struct extent_region *, struct extent_region *); 78 static struct extent_region *extent_alloc_region_descriptor(struct extent *, int); 79 static void extent_free_region_descriptor(struct extent *, 80 struct extent_region *); 81 82 /* 83 * Shortcut to align to an arbitrary power-of-two boundary. 84 */ 85 static __inline__ u_long 86 extent_align(u_long start, u_long align, u_long skew) 87 { 88 return ((((start - skew) + (align - 1)) & (-align)) + skew); 89 } 90 91 92 #if defined(DIAGNOSTIC) || defined(DDB) 93 /* 94 * Register the extent on a doubly linked list. 95 * Should work, no? 96 */ 97 static LIST_HEAD(listhead, extent) ext_list; 98 static void extent_register(struct extent *); 99 100 static void 101 extent_register(struct extent *ex) 102 { 103 #ifdef DIAGNOSTIC 104 struct extent *ep; 105 #endif 106 static int initialized; 107 108 if (!initialized){ 109 LIST_INIT(&ext_list); 110 initialized = 1; 111 } 112 113 #ifdef DIAGNOSTIC 114 LIST_FOREACH(ep, &ext_list, ex_link) { 115 if (ep == ex) 116 panic("%s: already registered", __func__); 117 } 118 #endif 119 120 /* Insert into list */ 121 LIST_INSERT_HEAD(&ext_list, ex, ex_link); 122 } 123 #endif /* DIAGNOSTIC || DDB */ 124 125 struct pool ex_region_pl; 126 127 static void 128 extent_pool_init(void) 129 { 130 static int inited; 131 132 if (!inited) { 133 pool_init(&ex_region_pl, sizeof(struct extent_region), 0, 0, 0, 134 "extentpl", NULL); 135 pool_setipl(&ex_region_pl, IPL_VM); 136 inited = 1; 137 } 138 } 139 140 #ifdef DDB 141 /* 142 * Print out all extents registered. This is used in 143 * DDB show extents 144 */ 145 void 146 extent_print_all(void) 147 { 148 struct extent *ep; 149 150 LIST_FOREACH(ep, &ext_list, ex_link) { 151 extent_print1(ep, db_printf); 152 } 153 } 154 #endif 155 156 /* 157 * Allocate and initialize an extent map. 158 */ 159 struct extent * 160 extent_create(char *name, u_long start, u_long end, int mtype, caddr_t storage, 161 size_t storagesize, int flags) 162 { 163 struct extent *ex; 164 caddr_t cp = storage; 165 size_t sz = storagesize; 166 struct extent_region *rp; 167 int fixed_extent = (storage != NULL); 168 169 #ifdef DIAGNOSTIC 170 /* Check arguments. */ 171 if (name == NULL) 172 panic("%s: name == NULL", __func__); 173 if (end < start) { 174 printf("%s: extent `%s', start 0x%lx, end 0x%lx\n", 175 __func__, name, start, end); 176 panic("%s: end < start", __func__); 177 } 178 if (fixed_extent && (storagesize < sizeof(struct extent_fixed))) 179 panic("%s: fixed extent, bad storagesize 0x%lx", 180 __func__, (u_long)storagesize); 181 if (fixed_extent == 0 && (storagesize != 0 || storage != NULL)) 182 panic("%s: storage provided for non-fixed", __func__); 183 #endif 184 185 extent_pool_init(); 186 187 /* Allocate extent descriptor. */ 188 if (fixed_extent) { 189 struct extent_fixed *fex; 190 191 memset(storage, 0, storagesize); 192 193 /* 194 * Align all descriptors on "long" boundaries. 195 */ 196 fex = (struct extent_fixed *)cp; 197 ex = (struct extent *)fex; 198 cp += ALIGN(sizeof(struct extent_fixed)); 199 sz -= ALIGN(sizeof(struct extent_fixed)); 200 fex->fex_storage = storage; 201 fex->fex_storagesize = storagesize; 202 203 /* 204 * In a fixed extent, we have to pre-allocate region 205 * descriptors and place them in the extent's freelist. 206 */ 207 LIST_INIT(&fex->fex_freelist); 208 while (sz >= ALIGN(sizeof(struct extent_region))) { 209 rp = (struct extent_region *)cp; 210 cp += ALIGN(sizeof(struct extent_region)); 211 sz -= ALIGN(sizeof(struct extent_region)); 212 LIST_INSERT_HEAD(&fex->fex_freelist, rp, er_link); 213 } 214 } else { 215 ex = (struct extent *)malloc(sizeof(struct extent), 216 mtype, (flags & EX_WAITOK) ? M_WAITOK : M_NOWAIT); 217 if (ex == NULL) 218 return (NULL); 219 } 220 221 /* Fill in the extent descriptor and return it to the caller. */ 222 LIST_INIT(&ex->ex_regions); 223 ex->ex_name = name; 224 ex->ex_start = start; 225 ex->ex_end = end; 226 ex->ex_mtype = mtype; 227 ex->ex_flags = 0; 228 if (fixed_extent) 229 ex->ex_flags |= EXF_FIXED; 230 if (flags & EX_NOCOALESCE) 231 ex->ex_flags |= EXF_NOCOALESCE; 232 233 if (flags & EX_FILLED) { 234 rp = extent_alloc_region_descriptor(ex, flags); 235 if (rp == NULL) { 236 if (!fixed_extent) 237 free(ex, mtype); 238 return (NULL); 239 } 240 rp->er_start = start; 241 rp->er_end = end; 242 LIST_INSERT_HEAD(&ex->ex_regions, rp, er_link); 243 } 244 245 #if defined(DIAGNOSTIC) || defined(DDB) 246 extent_register(ex); 247 #endif 248 return (ex); 249 } 250 251 /* 252 * Destroy an extent map. 253 */ 254 void 255 extent_destroy(struct extent *ex) 256 { 257 struct extent_region *rp, *orp; 258 259 #ifdef DIAGNOSTIC 260 /* Check arguments. */ 261 if (ex == NULL) 262 panic("%s: NULL extent", __func__); 263 #endif 264 265 /* Free all region descriptors in extent. */ 266 for (rp = LIST_FIRST(&ex->ex_regions); 267 rp != LIST_END(&ex->ex_regions); ) { 268 orp = rp; 269 rp = LIST_NEXT(rp, er_link); 270 LIST_REMOVE(orp, er_link); 271 extent_free_region_descriptor(ex, orp); 272 } 273 274 #if defined(DIAGNOSTIC) || defined(DDB) 275 /* Remove from the list of all extents. */ 276 LIST_REMOVE(ex, ex_link); 277 #endif 278 279 /* If we're not a fixed extent, free the extent descriptor itself. */ 280 if ((ex->ex_flags & EXF_FIXED) == 0) 281 free(ex, ex->ex_mtype); 282 } 283 284 /* 285 * Insert a region descriptor into the sorted region list after the 286 * entry "after" or at the head of the list (if "after" is NULL). 287 * The region descriptor we insert is passed in "rp". We must 288 * allocate the region descriptor before calling this function! 289 * If we don't need the region descriptor, it will be freed here. 290 */ 291 static void 292 extent_insert_and_optimize(struct extent *ex, u_long start, u_long size, 293 struct extent_region *after, struct extent_region *rp) 294 { 295 struct extent_region *nextr; 296 int appended = 0; 297 298 if (after == NULL) { 299 /* 300 * We're the first in the region list. If there's 301 * a region after us, attempt to coalesce to save 302 * descriptor overhead. 303 */ 304 if (((ex->ex_flags & EXF_NOCOALESCE) == 0) && 305 !LIST_EMPTY(&ex->ex_regions) && 306 ((start + size) == LIST_FIRST(&ex->ex_regions)->er_start)) { 307 /* 308 * We can coalesce. Prepend us to the first region. 309 */ 310 LIST_FIRST(&ex->ex_regions)->er_start = start; 311 extent_free_region_descriptor(ex, rp); 312 return; 313 } 314 315 /* 316 * Can't coalesce. Fill in the region descriptor 317 * in, and insert us at the head of the region list. 318 */ 319 rp->er_start = start; 320 rp->er_end = start + (size - 1); 321 LIST_INSERT_HEAD(&ex->ex_regions, rp, er_link); 322 return; 323 } 324 325 /* 326 * If EXF_NOCOALESCE is set, coalescing is disallowed. 327 */ 328 if (ex->ex_flags & EXF_NOCOALESCE) 329 goto cant_coalesce; 330 331 /* 332 * Attempt to coalesce with the region before us. 333 */ 334 if ((after->er_end + 1) == start) { 335 /* 336 * We can coalesce. Append ourselves and make 337 * note of it. 338 */ 339 after->er_end = start + (size - 1); 340 appended = 1; 341 } 342 343 /* 344 * Attempt to coalesce with the region after us. 345 */ 346 if (LIST_NEXT(after, er_link) != NULL && 347 ((start + size) == LIST_NEXT(after, er_link)->er_start)) { 348 /* 349 * We can coalesce. Note that if we appended ourselves 350 * to the previous region, we exactly fit the gap, and 351 * can free the "next" region descriptor. 352 */ 353 if (appended) { 354 /* 355 * Yup, we can free it up. 356 */ 357 after->er_end = LIST_NEXT(after, er_link)->er_end; 358 nextr = LIST_NEXT(after, er_link); 359 LIST_REMOVE(nextr, er_link); 360 extent_free_region_descriptor(ex, nextr); 361 } else { 362 /* 363 * Nope, just prepend us to the next region. 364 */ 365 LIST_NEXT(after, er_link)->er_start = start; 366 } 367 368 extent_free_region_descriptor(ex, rp); 369 return; 370 } 371 372 /* 373 * We weren't able to coalesce with the next region, but 374 * we don't need to allocate a region descriptor if we 375 * appended ourselves to the previous region. 376 */ 377 if (appended) { 378 extent_free_region_descriptor(ex, rp); 379 return; 380 } 381 382 cant_coalesce: 383 384 /* 385 * Fill in the region descriptor and insert ourselves 386 * into the region list. 387 */ 388 rp->er_start = start; 389 rp->er_end = start + (size - 1); 390 LIST_INSERT_AFTER(after, rp, er_link); 391 } 392 393 /* 394 * Allocate a specific region in an extent map. 395 */ 396 int 397 extent_alloc_region(struct extent *ex, u_long start, u_long size, int flags) 398 { 399 struct extent_region *rp, *last, *myrp; 400 u_long end = start + (size - 1); 401 int error; 402 403 #ifdef DIAGNOSTIC 404 /* Check arguments. */ 405 if (ex == NULL) 406 panic("%s: NULL extent", __func__); 407 if (size < 1) { 408 printf("%s: extent `%s', size 0x%lx\n", 409 __func__, ex->ex_name, size); 410 panic("%s: bad size", __func__); 411 } 412 if (end < start) { 413 printf("%s: extent `%s', start 0x%lx, size 0x%lx\n", 414 __func__, ex->ex_name, start, size); 415 panic("%s: overflow", __func__); 416 } 417 if ((flags & EX_CONFLICTOK) && (flags & EX_WAITSPACE)) 418 panic("%s: EX_CONFLICTOK and EX_WAITSPACE " 419 "are mutually exclusive", __func__); 420 #endif 421 422 /* 423 * Make sure the requested region lies within the 424 * extent. 425 */ 426 if ((start < ex->ex_start) || (end > ex->ex_end)) { 427 #ifdef DIAGNOSTIC 428 printf("%s: extent `%s' (0x%lx - 0x%lx)\n", 429 __func__, ex->ex_name, ex->ex_start, ex->ex_end); 430 printf("%s: start 0x%lx, end 0x%lx\n", 431 __func__, start, end); 432 panic("%s: region lies outside extent", __func__); 433 #else 434 return (EINVAL); 435 #endif 436 } 437 438 /* 439 * Allocate the region descriptor. It will be freed later 440 * if we can coalesce with another region. 441 */ 442 myrp = extent_alloc_region_descriptor(ex, flags); 443 if (myrp == NULL) { 444 #ifdef DIAGNOSTIC 445 printf( 446 "%s: can't allocate region descriptor\n", __func__); 447 #endif 448 return (ENOMEM); 449 } 450 451 alloc_start: 452 /* 453 * Attempt to place ourselves in the desired area of the 454 * extent. We save ourselves some work by keeping the list sorted. 455 * In other words, if the start of the current region is greater 456 * than the end of our region, we don't have to search any further. 457 */ 458 459 /* 460 * Keep a pointer to the last region we looked at so 461 * that we don't have to traverse the list again when 462 * we insert ourselves. If "last" is NULL when we 463 * finally insert ourselves, we go at the head of the 464 * list. See extent_insert_and_optimize() for details. 465 */ 466 last = NULL; 467 468 LIST_FOREACH(rp, &ex->ex_regions, er_link) { 469 if (rp->er_start > end) { 470 /* 471 * We lie before this region and don't 472 * conflict. 473 */ 474 break; 475 } 476 477 /* 478 * The current region begins before we end. 479 * Check for a conflict. 480 */ 481 if (rp->er_end >= start) { 482 /* 483 * We conflict. If we can (and want to) wait, 484 * do so. 485 */ 486 if (flags & EX_WAITSPACE) { 487 ex->ex_flags |= EXF_WANTED; 488 error = tsleep(ex, 489 PRIBIO | ((flags & EX_CATCH) ? PCATCH : 0), 490 "extnt", 0); 491 if (error) 492 return (error); 493 goto alloc_start; 494 } 495 496 /* 497 * If we tolerate conflicts adjust things such 498 * that all space in the requested region is 499 * allocated. 500 */ 501 if (flags & EX_CONFLICTOK) { 502 /* 503 * There are four possibilities: 504 * 505 * 1. The current region overlaps with 506 * the start of the requested region. 507 * Adjust the requested region to 508 * start at the end of the current 509 * region and try again. 510 * 511 * 2. The current region falls 512 * completely within the requested 513 * region. Free the current region 514 * and try again. 515 * 516 * 3. The current region overlaps with 517 * the end of the requested region. 518 * Adjust the requested region to 519 * end at the start of the current 520 * region and try again. 521 * 522 * 4. The requested region falls 523 * completely within the current 524 * region. We're done. 525 */ 526 if (rp->er_start <= start) { 527 if (rp->er_end < ex->ex_end) { 528 start = rp->er_end + 1; 529 size = end - start + 1; 530 goto alloc_start; 531 } 532 } else if (rp->er_end < end) { 533 LIST_REMOVE(rp, er_link); 534 extent_free_region_descriptor(ex, rp); 535 goto alloc_start; 536 } else if (rp->er_start < end) { 537 if (rp->er_start > ex->ex_start) { 538 end = rp->er_start - 1; 539 size = end - start + 1; 540 goto alloc_start; 541 } 542 } 543 return (0); 544 } 545 546 extent_free_region_descriptor(ex, myrp); 547 return (EAGAIN); 548 } 549 /* 550 * We don't conflict, but this region lies before 551 * us. Keep a pointer to this region, and keep 552 * trying. 553 */ 554 last = rp; 555 } 556 557 /* 558 * We don't conflict with any regions. "last" points 559 * to the region we fall after, or is NULL if we belong 560 * at the beginning of the region list. Insert ourselves. 561 */ 562 extent_insert_and_optimize(ex, start, size, last, myrp); 563 return (0); 564 } 565 566 /* 567 * Macro to check (x + y) <= z. This check is designed to fail 568 * if an overflow occurs. 569 */ 570 #define LE_OV(x, y, z) ((((x) + (y)) >= (x)) && (((x) + (y)) <= (z))) 571 572 /* 573 * Allocate a region in an extent map subregion. 574 * 575 * If EX_FAST is specified, we return the first fit in the map. 576 * Otherwise, we try to minimize fragmentation by finding the 577 * smallest gap that will hold the request. 578 * 579 * The allocated region is aligned to "alignment", which must be 580 * a power of 2. 581 */ 582 int 583 extent_alloc_subregion(struct extent *ex, u_long substart, u_long subend, 584 u_long size, u_long alignment, u_long skew, u_long boundary, int flags, 585 u_long *result) 586 { 587 struct extent_region *rp, *myrp, *last, *bestlast; 588 u_long newstart, newend, exend, beststart, bestovh, ovh; 589 u_long dontcross; 590 int error; 591 592 #ifdef DIAGNOSTIC 593 /* Check arguments. */ 594 if (ex == NULL) 595 panic("%s: NULL extent", __func__); 596 if (result == NULL) 597 panic("%s: NULL result pointer", __func__); 598 if ((substart < ex->ex_start) || (substart > ex->ex_end) || 599 (subend > ex->ex_end) || (subend < ex->ex_start)) { 600 printf("%s: extent `%s', ex_start 0x%lx, ex_end 0x%lx\n", 601 __func__, ex->ex_name, ex->ex_start, ex->ex_end); 602 printf("%s: substart 0x%lx, subend 0x%lx\n", 603 __func__, substart, subend); 604 panic("%s: bad subregion", __func__); 605 } 606 if ((size < 1) || ((size - 1) > (subend - substart))) { 607 printf("%s: extent `%s', size 0x%lx\n", 608 __func__, ex->ex_name, size); 609 panic("%s: bad size", __func__); 610 } 611 if (alignment == 0) 612 panic("%s: bad alignment", __func__); 613 if (boundary && (boundary < size)) { 614 printf("%s: extent `%s', size 0x%lx, boundary 0x%lx\n", 615 __func__, ex->ex_name, size, boundary); 616 panic("%s: bad boundary", __func__); 617 } 618 #endif 619 620 /* 621 * Allocate the region descriptor. It will be freed later 622 * if we can coalesce with another region. 623 */ 624 myrp = extent_alloc_region_descriptor(ex, flags); 625 if (myrp == NULL) { 626 #ifdef DIAGNOSTIC 627 printf("%s: can't allocate region descriptor\n", __func__); 628 #endif 629 return (ENOMEM); 630 } 631 632 alloc_start: 633 /* 634 * Keep a pointer to the last region we looked at so 635 * that we don't have to traverse the list again when 636 * we insert ourselves. If "last" is NULL when we 637 * finally insert ourselves, we go at the head of the 638 * list. See extent_insert_and_optimize() for details. 639 */ 640 last = NULL; 641 642 /* 643 * Keep track of size and location of the smallest 644 * chunk we fit in. 645 * 646 * Since the extent can be as large as the numeric range 647 * of the CPU (0 - 0xffffffff for 32-bit systems), the 648 * best overhead value can be the maximum unsigned integer. 649 * Thus, we initialize "bestovh" to 0, since we insert ourselves 650 * into the region list immediately on an exact match (which 651 * is the only case where "bestovh" would be set to 0). 652 */ 653 bestovh = 0; 654 beststart = 0; 655 bestlast = NULL; 656 657 /* 658 * Keep track of end of free region. This is either the end of extent 659 * or the start of a region past the subend. 660 */ 661 exend = ex->ex_end; 662 663 /* 664 * For N allocated regions, we must make (N + 1) 665 * checks for unallocated space. The first chunk we 666 * check is the area from the beginning of the subregion 667 * to the first allocated region after that point. 668 */ 669 newstart = extent_align(substart, alignment, skew); 670 if (newstart < ex->ex_start) { 671 #ifdef DIAGNOSTIC 672 printf("%s: extent `%s' (0x%lx - 0x%lx), alignment 0x%lx\n", 673 __func__, ex->ex_name, ex->ex_start, ex->ex_end, 674 alignment); 675 panic("%s: overflow after alignment", __func__); 676 #else 677 extent_free_region_descriptor(ex, myrp); 678 return (EINVAL); 679 #endif 680 } 681 682 /* 683 * Find the first allocated region that begins on or after 684 * the subregion start, advancing the "last" pointer along 685 * the way. 686 */ 687 LIST_FOREACH(rp, &ex->ex_regions, er_link) { 688 if (rp->er_start >= newstart) 689 break; 690 last = rp; 691 } 692 693 /* 694 * Relocate the start of our candidate region to the end of 695 * the last allocated region (if there was one overlapping 696 * our subrange). 697 */ 698 if (last != NULL && last->er_end >= newstart) 699 newstart = extent_align((last->er_end + 1), alignment, skew); 700 701 for (; rp != LIST_END(&ex->ex_regions); rp = LIST_NEXT(rp, er_link)) { 702 /* 703 * If the region pasts the subend, bail out and see 704 * if we fit against the subend. 705 */ 706 if (rp->er_start > subend) { 707 exend = rp->er_start; 708 break; 709 } 710 711 /* 712 * Check the chunk before "rp". Note that our 713 * comparison is safe from overflow conditions. 714 */ 715 if (LE_OV(newstart, size, rp->er_start)) { 716 /* 717 * Do a boundary check, if necessary. Note 718 * that a region may *begin* on the boundary, 719 * but it must end before the boundary. 720 */ 721 if (boundary) { 722 newend = newstart + (size - 1); 723 724 /* 725 * Calculate the next boundary after the start 726 * of this region. 727 */ 728 dontcross = extent_align(newstart+1, boundary, 729 (flags & EX_BOUNDZERO) ? 0 : ex->ex_start) 730 - 1; 731 732 #if 0 733 printf("newstart=%lx newend=%lx ex_start=%lx ex_end=%lx boundary=%lx dontcross=%lx\n", 734 newstart, newend, ex->ex_start, ex->ex_end, 735 boundary, dontcross); 736 #endif 737 738 /* Check for overflow */ 739 if (dontcross < ex->ex_start) 740 dontcross = ex->ex_end; 741 else if (newend > dontcross) { 742 /* 743 * Candidate region crosses boundary. 744 * Throw away the leading part and see 745 * if we still fit. 746 */ 747 newstart = dontcross + 1; 748 newend = newstart + (size - 1); 749 dontcross += boundary; 750 if (!LE_OV(newstart, size, rp->er_start)) 751 goto skip; 752 } 753 754 /* 755 * If we run past the end of 756 * the extent or the boundary 757 * overflows, then the request 758 * can't fit. 759 */ 760 if (newstart + size - 1 > ex->ex_end || 761 dontcross < newstart) 762 goto fail; 763 } 764 765 /* 766 * We would fit into this space. Calculate 767 * the overhead (wasted space). If we exactly 768 * fit, or we're taking the first fit, insert 769 * ourselves into the region list. 770 */ 771 ovh = rp->er_start - newstart - size; 772 if ((flags & EX_FAST) || (ovh == 0)) 773 goto found; 774 775 /* 776 * Don't exactly fit, but check to see 777 * if we're better than any current choice. 778 */ 779 if ((bestovh == 0) || (ovh < bestovh)) { 780 bestovh = ovh; 781 beststart = newstart; 782 bestlast = last; 783 } 784 } 785 786 skip: 787 /* 788 * Skip past the current region and check again. 789 */ 790 newstart = extent_align((rp->er_end + 1), alignment, skew); 791 if (newstart < rp->er_end) { 792 /* 793 * Overflow condition. Don't error out, since 794 * we might have a chunk of space that we can 795 * use. 796 */ 797 goto fail; 798 } 799 800 last = rp; 801 } 802 803 /* 804 * The final check is from the current starting point to the 805 * end of the subregion. If there were no allocated regions, 806 * "newstart" is set to the beginning of the subregion, or 807 * just past the end of the last allocated region, adjusted 808 * for alignment in either case. 809 */ 810 if (LE_OV(newstart, (size - 1), subend)) { 811 /* 812 * Do a boundary check, if necessary. Note 813 * that a region may *begin* on the boundary, 814 * but it must end before the boundary. 815 */ 816 if (boundary) { 817 newend = newstart + (size - 1); 818 819 /* 820 * Calculate the next boundary after the start 821 * of this region. 822 */ 823 dontcross = extent_align(newstart+1, boundary, 824 (flags & EX_BOUNDZERO) ? 0 : ex->ex_start) 825 - 1; 826 827 #if 0 828 printf("newstart=%lx newend=%lx ex_start=%lx ex_end=%lx boundary=%lx dontcross=%lx\n", 829 newstart, newend, ex->ex_start, ex->ex_end, 830 boundary, dontcross); 831 #endif 832 833 /* Check for overflow */ 834 if (dontcross < ex->ex_start) 835 dontcross = ex->ex_end; 836 else if (newend > dontcross) { 837 /* 838 * Candidate region crosses boundary. 839 * Throw away the leading part and see 840 * if we still fit. 841 */ 842 newstart = dontcross + 1; 843 newend = newstart + (size - 1); 844 dontcross += boundary; 845 if (!LE_OV(newstart, (size - 1), subend)) 846 goto fail; 847 } 848 849 /* 850 * If we run past the end of 851 * the extent or the boundary 852 * overflows, then the request 853 * can't fit. 854 */ 855 if (newstart + size - 1 > ex->ex_end || 856 dontcross < newstart) 857 goto fail; 858 } 859 860 /* 861 * We would fit into this space. Calculate 862 * the overhead (wasted space). If we exactly 863 * fit, or we're taking the first fit, insert 864 * ourselves into the region list. 865 */ 866 ovh = exend - newstart - (size - 1); 867 if ((flags & EX_FAST) || (ovh == 0)) 868 goto found; 869 870 /* 871 * Don't exactly fit, but check to see 872 * if we're better than any current choice. 873 */ 874 if ((bestovh == 0) || (ovh < bestovh)) { 875 bestovh = ovh; 876 beststart = newstart; 877 bestlast = last; 878 } 879 } 880 881 fail: 882 /* 883 * One of the following two conditions have 884 * occurred: 885 * 886 * There is no chunk large enough to hold the request. 887 * 888 * If EX_FAST was not specified, there is not an 889 * exact match for the request. 890 * 891 * Note that if we reach this point and EX_FAST is 892 * set, then we know there is no space in the extent for 893 * the request. 894 */ 895 if (((flags & EX_FAST) == 0) && (bestovh != 0)) { 896 /* 897 * We have a match that's "good enough". 898 */ 899 newstart = beststart; 900 last = bestlast; 901 goto found; 902 } 903 904 /* 905 * No space currently available. Wait for it to free up, 906 * if possible. 907 */ 908 if (flags & EX_WAITSPACE) { 909 ex->ex_flags |= EXF_WANTED; 910 error = tsleep(ex, 911 PRIBIO | ((flags & EX_CATCH) ? PCATCH : 0), "extnt", 0); 912 if (error) 913 return (error); 914 goto alloc_start; 915 } 916 917 extent_free_region_descriptor(ex, myrp); 918 return (EAGAIN); 919 920 found: 921 /* 922 * Insert ourselves into the region list. 923 */ 924 extent_insert_and_optimize(ex, newstart, size, last, myrp); 925 *result = newstart; 926 return (0); 927 } 928 929 int 930 extent_free(struct extent *ex, u_long start, u_long size, int flags) 931 { 932 struct extent_region *rp, *nrp = NULL; 933 u_long end = start + (size - 1); 934 int exflags; 935 936 #ifdef DIAGNOSTIC 937 /* Check arguments. */ 938 if (ex == NULL) 939 panic("%s: NULL extent", __func__); 940 if ((start < ex->ex_start) || (end > ex->ex_end)) { 941 extent_print(ex); 942 printf("%s: extent `%s', start 0x%lx, size 0x%lx\n", 943 __func__, ex->ex_name, start, size); 944 panic("%s: extent `%s', region not within extent", 945 __func__, ex->ex_name); 946 } 947 /* Check for an overflow. */ 948 if (end < start) { 949 extent_print(ex); 950 printf("%s: extent `%s', start 0x%lx, size 0x%lx\n", 951 __func__, ex->ex_name, start, size); 952 panic("%s: overflow", __func__); 953 } 954 #endif 955 956 /* 957 * If we're allowing coalescing, we must allocate a region 958 * descriptor now, since it might block. 959 * 960 * XXX Make a static, create-time flags word, so we don't 961 * XXX have to lock to read it! 962 */ 963 exflags = ex->ex_flags; 964 965 if ((exflags & EXF_NOCOALESCE) == 0) { 966 /* Allocate a region descriptor. */ 967 nrp = extent_alloc_region_descriptor(ex, flags); 968 if (nrp == NULL) 969 return (ENOMEM); 970 } 971 972 /* 973 * Find region and deallocate. Several possibilities: 974 * 975 * 1. (start == er_start) && (end == er_end): 976 * Free descriptor. 977 * 978 * 2. (start == er_start) && (end < er_end): 979 * Adjust er_start. 980 * 981 * 3. (start > er_start) && (end == er_end): 982 * Adjust er_end. 983 * 984 * 4. (start > er_start) && (end < er_end): 985 * Fragment region. Requires descriptor alloc. 986 * 987 * Cases 2, 3, and 4 require that the EXF_NOCOALESCE flag 988 * is not set. 989 */ 990 LIST_FOREACH(rp, &ex->ex_regions, er_link) { 991 /* 992 * Save ourselves some comparisons; does the current 993 * region end before chunk to be freed begins? If so, 994 * then we haven't found the appropriate region descriptor. 995 */ 996 if (rp->er_end < start) 997 continue; 998 999 /* 1000 * Save ourselves some traversal; does the current 1001 * region begin after the chunk to be freed ends? If so, 1002 * then we've already passed any possible region descriptors 1003 * that might have contained the chunk to be freed. 1004 */ 1005 if (rp->er_start > end) 1006 break; 1007 1008 /* Case 1. */ 1009 if ((start == rp->er_start) && (end == rp->er_end)) { 1010 LIST_REMOVE(rp, er_link); 1011 extent_free_region_descriptor(ex, rp); 1012 goto done; 1013 } 1014 1015 /* 1016 * The following cases all require that EXF_NOCOALESCE 1017 * is not set. 1018 */ 1019 if (ex->ex_flags & EXF_NOCOALESCE) 1020 continue; 1021 1022 /* Case 2. */ 1023 if ((start == rp->er_start) && (end < rp->er_end)) { 1024 rp->er_start = (end + 1); 1025 goto done; 1026 } 1027 1028 /* Case 3. */ 1029 if ((start > rp->er_start) && (end == rp->er_end)) { 1030 rp->er_end = (start - 1); 1031 goto done; 1032 } 1033 1034 /* Case 4. */ 1035 if ((start > rp->er_start) && (end < rp->er_end)) { 1036 /* Fill in new descriptor. */ 1037 nrp->er_start = end + 1; 1038 nrp->er_end = rp->er_end; 1039 1040 /* Adjust current descriptor. */ 1041 rp->er_end = start - 1; 1042 1043 /* Insert new descriptor after current. */ 1044 LIST_INSERT_AFTER(rp, nrp, er_link); 1045 1046 /* We used the new descriptor, so don't free it below */ 1047 nrp = NULL; 1048 goto done; 1049 } 1050 } 1051 1052 /* Region not found, or request otherwise invalid. */ 1053 #if defined(DIAGNOSTIC) || defined(DDB) 1054 extent_print(ex); 1055 #endif 1056 printf("%s: start 0x%lx, end 0x%lx\n", __func__, start, end); 1057 panic("%s: region not found", __func__); 1058 1059 done: 1060 if (nrp != NULL) 1061 extent_free_region_descriptor(ex, nrp); 1062 if (ex->ex_flags & EXF_WANTED) { 1063 ex->ex_flags &= ~EXF_WANTED; 1064 wakeup(ex); 1065 } 1066 return (0); 1067 } 1068 1069 static struct extent_region * 1070 extent_alloc_region_descriptor(struct extent *ex, int flags) 1071 { 1072 struct extent_region *rp; 1073 1074 if (ex->ex_flags & EXF_FIXED) { 1075 struct extent_fixed *fex = (struct extent_fixed *)ex; 1076 1077 while (LIST_EMPTY(&fex->fex_freelist)) { 1078 if (flags & EX_MALLOCOK) 1079 goto alloc; 1080 1081 if ((flags & EX_WAITOK) == 0) 1082 return (NULL); 1083 ex->ex_flags |= EXF_FLWANTED; 1084 if (tsleep(&fex->fex_freelist, 1085 PRIBIO | ((flags & EX_CATCH) ? PCATCH : 0), 1086 "extnt", 0)) 1087 return (NULL); 1088 } 1089 rp = LIST_FIRST(&fex->fex_freelist); 1090 LIST_REMOVE(rp, er_link); 1091 1092 /* 1093 * Don't muck with flags after pulling it off the 1094 * freelist; it may be a dynamically allocated 1095 * region pointer that was kindly given to us, 1096 * and we need to preserve that information. 1097 */ 1098 1099 return (rp); 1100 } 1101 1102 alloc: 1103 rp = pool_get(&ex_region_pl, (flags & EX_WAITOK) ? PR_WAITOK : 1104 PR_NOWAIT); 1105 if (rp != NULL) 1106 rp->er_flags = ER_ALLOC; 1107 1108 return (rp); 1109 } 1110 1111 static void 1112 extent_free_region_descriptor(struct extent *ex, struct extent_region *rp) 1113 { 1114 if (ex->ex_flags & EXF_FIXED) { 1115 struct extent_fixed *fex = (struct extent_fixed *)ex; 1116 1117 /* 1118 * If someone's waiting for a region descriptor, 1119 * be nice and give them this one, rather than 1120 * just free'ing it back to the system. 1121 */ 1122 if (rp->er_flags & ER_ALLOC) { 1123 if (ex->ex_flags & EXF_FLWANTED) { 1124 /* Clear all but ER_ALLOC flag. */ 1125 rp->er_flags = ER_ALLOC; 1126 LIST_INSERT_HEAD(&fex->fex_freelist, rp, 1127 er_link); 1128 goto wake_em_up; 1129 } else { 1130 pool_put(&ex_region_pl, rp); 1131 } 1132 } else { 1133 /* Clear all flags. */ 1134 rp->er_flags = 0; 1135 LIST_INSERT_HEAD(&fex->fex_freelist, rp, er_link); 1136 } 1137 1138 if (ex->ex_flags & EXF_FLWANTED) { 1139 wake_em_up: 1140 ex->ex_flags &= ~EXF_FLWANTED; 1141 wakeup(&fex->fex_freelist); 1142 } 1143 return; 1144 } 1145 1146 /* 1147 * We know it's dynamically allocated if we get here. 1148 */ 1149 pool_put(&ex_region_pl, rp); 1150 } 1151 1152 1153 #if defined(DIAGNOSTIC) || defined(DDB) || !defined(_KERNEL) 1154 1155 void 1156 extent_print(struct extent *ex) 1157 { 1158 extent_print1(ex, printf); 1159 } 1160 1161 void 1162 extent_print1(struct extent *ex, 1163 int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) 1164 { 1165 struct extent_region *rp; 1166 1167 if (ex == NULL) 1168 panic("%s: NULL extent", __func__); 1169 1170 #ifdef _KERNEL 1171 (*pr)("extent `%s' (0x%lx - 0x%lx), flags=%b\n", ex->ex_name, 1172 ex->ex_start, ex->ex_end, ex->ex_flags, EXF_BITS); 1173 #else 1174 (*pr)("extent `%s' (0x%lx - 0x%lx), flags = 0x%x\n", ex->ex_name, 1175 ex->ex_start, ex->ex_end, ex->ex_flags); 1176 #endif 1177 1178 LIST_FOREACH(rp, &ex->ex_regions, er_link) 1179 (*pr)(" 0x%lx - 0x%lx\n", rp->er_start, rp->er_end); 1180 } 1181 #endif 1182