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