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