1 /* 2 * Copyright (c) 2008 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $DragonFly: src/sys/vfs/hammer/hammer_blockmap.c,v 1.9 2008/04/29 01:10:37 dillon Exp $ 35 */ 36 37 /* 38 * HAMMER blockmap 39 */ 40 #include "hammer.h" 41 42 static hammer_off_t hammer_find_hole(hammer_mount_t hmp, 43 hammer_holes_t holes, int bytes); 44 static void hammer_add_hole(hammer_mount_t hmp, hammer_holes_t holes, 45 hammer_off_t offset, int bytes); 46 47 /* 48 * Allocate bytes from a zone 49 */ 50 hammer_off_t 51 hammer_blockmap_alloc(hammer_transaction_t trans, int zone, 52 int bytes, int *errorp) 53 { 54 hammer_volume_t root_volume; 55 hammer_blockmap_t rootmap; 56 struct hammer_blockmap_layer1 *layer1; 57 struct hammer_blockmap_layer2 *layer2; 58 hammer_buffer_t buffer1 = NULL; 59 hammer_buffer_t buffer2 = NULL; 60 hammer_buffer_t buffer3 = NULL; 61 hammer_off_t tmp_offset; 62 hammer_off_t next_offset; 63 hammer_off_t layer1_offset; 64 hammer_off_t layer2_offset; 65 hammer_off_t bigblock_offset; 66 int loops = 0; 67 int skip_amount; 68 int used_hole; 69 70 KKASSERT(zone >= HAMMER_ZONE_BTREE_INDEX && zone < HAMMER_MAX_ZONES); 71 root_volume = hammer_get_root_volume(trans->hmp, errorp); 72 if (*errorp) 73 return(0); 74 rootmap = &trans->hmp->blockmap[zone]; 75 KKASSERT(rootmap->phys_offset != 0); 76 KKASSERT(HAMMER_ZONE_DECODE(rootmap->phys_offset) == 77 HAMMER_ZONE_RAW_BUFFER_INDEX); 78 KKASSERT(HAMMER_ZONE_DECODE(rootmap->alloc_offset) == zone); 79 KKASSERT(HAMMER_ZONE_DECODE(rootmap->next_offset) == zone); 80 81 /* 82 * Deal with alignment and buffer-boundary issues. 83 * 84 * Be careful, certain primary alignments are used below to allocate 85 * new blockmap blocks. 86 */ 87 bytes = (bytes + 7) & ~7; 88 KKASSERT(bytes > 0 && bytes <= HAMMER_BUFSIZE); 89 90 lockmgr(&trans->hmp->blockmap_lock, LK_EXCLUSIVE|LK_RETRY); 91 92 /* 93 * Try to use a known-free hole, otherwise append. 94 */ 95 next_offset = hammer_find_hole(trans->hmp, &trans->hmp->holes[zone], 96 bytes); 97 if (next_offset == 0) { 98 next_offset = rootmap->next_offset; 99 used_hole = 0; 100 } else { 101 used_hole = 1; 102 } 103 104 again: 105 /* 106 * The allocation request may not cross a buffer boundary. 107 */ 108 tmp_offset = next_offset + bytes - 1; 109 if ((next_offset ^ tmp_offset) & ~HAMMER_BUFMASK64) { 110 skip_amount = HAMMER_BUFSIZE - 111 ((int)next_offset & HAMMER_BUFMASK); 112 hammer_add_hole(trans->hmp, &trans->hmp->holes[zone], 113 next_offset, skip_amount); 114 next_offset = tmp_offset & ~HAMMER_BUFMASK64; 115 } 116 117 /* 118 * Dive layer 1. If we are starting a new layer 1 entry, 119 * allocate a layer 2 block for it. 120 */ 121 layer1_offset = rootmap->phys_offset + 122 HAMMER_BLOCKMAP_LAYER1_OFFSET(next_offset); 123 layer1 = hammer_bread(trans->hmp, layer1_offset, errorp, &buffer1); 124 KKASSERT(*errorp == 0); 125 KKASSERT(next_offset <= rootmap->alloc_offset); 126 127 /* 128 * Allocate layer2 backing store in layer1 if necessary. next_offset 129 * can skip to a bigblock boundary but alloc_offset is at least 130 * bigblock=aligned so that's ok. 131 */ 132 if (next_offset == rootmap->alloc_offset && 133 ((next_offset & HAMMER_BLOCKMAP_LAYER2_MASK) == 0 || 134 layer1->phys_offset == HAMMER_BLOCKMAP_FREE) 135 ) { 136 KKASSERT((next_offset & HAMMER_BLOCKMAP_LAYER2_MASK) == 0); 137 hammer_modify_buffer(trans, buffer1, layer1, sizeof(*layer1)); 138 bzero(layer1, sizeof(*layer1)); 139 layer1->phys_offset = 140 hammer_freemap_alloc(trans, next_offset, errorp); 141 layer1->blocks_free = HAMMER_BLOCKMAP_RADIX2; 142 hammer_modify_buffer_done(buffer1); 143 KKASSERT(*errorp == 0); 144 } 145 KKASSERT(layer1->phys_offset); 146 147 /* 148 * If layer1 indicates no free blocks in layer2 and our alloc_offset 149 * is not in layer2, skip layer2 entirely. 150 */ 151 if (layer1->blocks_free == 0 && 152 ((next_offset ^ rootmap->alloc_offset) & ~HAMMER_BLOCKMAP_LAYER2_MASK) != 0) { 153 kprintf("blockmap skip1 %016llx\n", next_offset); 154 next_offset = (next_offset + HAMMER_BLOCKMAP_LAYER2_MASK) & 155 ~HAMMER_BLOCKMAP_LAYER2_MASK; 156 if (next_offset >= trans->hmp->zone_limits[zone]) { 157 kprintf("blockmap wrap1\n"); 158 next_offset = HAMMER_ZONE_ENCODE(zone, 0); 159 if (++loops == 2) { /* XXX poor-man's */ 160 next_offset = 0; 161 *errorp = ENOSPC; 162 goto done; 163 } 164 } 165 goto again; 166 } 167 168 /* 169 * Dive layer 2, each entry represents a large-block. 170 */ 171 layer2_offset = layer1->phys_offset + 172 HAMMER_BLOCKMAP_LAYER2_OFFSET(next_offset); 173 layer2 = hammer_bread(trans->hmp, layer2_offset, errorp, &buffer2); 174 KKASSERT(*errorp == 0); 175 176 if ((next_offset & HAMMER_LARGEBLOCK_MASK64) == 0) { 177 /* 178 * We are at the beginning of a new bigblock 179 */ 180 if (next_offset == rootmap->alloc_offset || 181 layer2->u.phys_offset == HAMMER_BLOCKMAP_FREE) { 182 /* 183 * Allocate the bigblock in layer2 if diving into 184 * uninitialized space or if the block was previously 185 * freed. 186 */ 187 hammer_modify_buffer(trans, buffer1, 188 layer1, sizeof(*layer1)); 189 KKASSERT(layer1->blocks_free); 190 --layer1->blocks_free; 191 hammer_modify_buffer_done(buffer1); 192 hammer_modify_buffer(trans, buffer2, 193 layer2, sizeof(*layer2)); 194 bzero(layer2, sizeof(*layer2)); 195 layer2->u.phys_offset = 196 hammer_freemap_alloc(trans, next_offset, 197 errorp); 198 layer2->bytes_free = HAMMER_LARGEBLOCK_SIZE; 199 hammer_modify_buffer_done(buffer2); 200 KKASSERT(*errorp == 0); 201 } else if (layer2->bytes_free != HAMMER_LARGEBLOCK_SIZE) { 202 /* 203 * We have encountered a block that is already 204 * partially allocated. We must skip this block. 205 */ 206 kprintf("blockmap skip2 %016llx %d\n", 207 next_offset, layer2->bytes_free); 208 next_offset += HAMMER_LARGEBLOCK_SIZE; 209 if (next_offset >= trans->hmp->zone_limits[zone]) { 210 next_offset = HAMMER_ZONE_ENCODE(zone, 0); 211 kprintf("blockmap wrap2\n"); 212 if (++loops == 2) { /* XXX poor-man's */ 213 next_offset = 0; 214 *errorp = ENOSPC; 215 goto done; 216 } 217 } 218 goto again; 219 } 220 } else { 221 /* 222 * We are appending within a bigblock. 223 */ 224 KKASSERT(layer2->u.phys_offset != HAMMER_BLOCKMAP_FREE); 225 } 226 227 hammer_modify_buffer(trans, buffer2, layer2, sizeof(*layer2)); 228 layer2->bytes_free -= bytes; 229 hammer_modify_buffer_done(buffer2); 230 KKASSERT(layer2->bytes_free >= 0); 231 232 /* 233 * If the buffer was completely free we do not have to read it from 234 * disk, call hammer_bnew() to instantiate it. 235 */ 236 if ((next_offset & HAMMER_BUFMASK) == 0) { 237 bigblock_offset = layer2->u.phys_offset + 238 (next_offset & HAMMER_LARGEBLOCK_MASK64); 239 hammer_bnew(trans->hmp, bigblock_offset, errorp, &buffer3); 240 } 241 242 /* 243 * Adjust our iterator and alloc_offset. The layer1 and layer2 244 * space beyond alloc_offset is uninitialized. alloc_offset must 245 * be big-block aligned. 246 */ 247 if (used_hole == 0) { 248 hammer_modify_volume(trans, root_volume, NULL, 0); 249 rootmap->next_offset = next_offset + bytes; 250 if (rootmap->alloc_offset < rootmap->next_offset) { 251 rootmap->alloc_offset = 252 (rootmap->next_offset + HAMMER_LARGEBLOCK_MASK) & 253 ~HAMMER_LARGEBLOCK_MASK64; 254 } 255 hammer_modify_volume_done(root_volume); 256 } 257 done: 258 if (buffer1) 259 hammer_rel_buffer(buffer1, 0); 260 if (buffer2) 261 hammer_rel_buffer(buffer2, 0); 262 if (buffer3) 263 hammer_rel_buffer(buffer3, 0); 264 hammer_rel_volume(root_volume, 0); 265 lockmgr(&trans->hmp->blockmap_lock, LK_RELEASE); 266 return(next_offset); 267 } 268 269 /* 270 * Free (offset,bytes) in a zone 271 */ 272 void 273 hammer_blockmap_free(hammer_transaction_t trans, 274 hammer_off_t bmap_off, int bytes) 275 { 276 hammer_volume_t root_volume; 277 hammer_blockmap_t rootmap; 278 struct hammer_blockmap_layer1 *layer1; 279 struct hammer_blockmap_layer2 *layer2; 280 hammer_buffer_t buffer1 = NULL; 281 hammer_buffer_t buffer2 = NULL; 282 hammer_off_t layer1_offset; 283 hammer_off_t layer2_offset; 284 int error; 285 int zone; 286 287 bytes = (bytes + 7) & ~7; 288 KKASSERT(bytes <= HAMMER_BUFSIZE); 289 zone = HAMMER_ZONE_DECODE(bmap_off); 290 KKASSERT(zone >= HAMMER_ZONE_BTREE_INDEX && zone < HAMMER_MAX_ZONES); 291 root_volume = hammer_get_root_volume(trans->hmp, &error); 292 if (error) 293 return; 294 295 lockmgr(&trans->hmp->blockmap_lock, LK_EXCLUSIVE|LK_RETRY); 296 297 rootmap = &trans->hmp->blockmap[zone]; 298 KKASSERT(rootmap->phys_offset != 0); 299 KKASSERT(HAMMER_ZONE_DECODE(rootmap->phys_offset) == 300 HAMMER_ZONE_RAW_BUFFER_INDEX); 301 KKASSERT(HAMMER_ZONE_DECODE(rootmap->alloc_offset) == zone); 302 KKASSERT(((bmap_off ^ (bmap_off + (bytes - 1))) & 303 ~HAMMER_LARGEBLOCK_MASK64) == 0); 304 305 if (bmap_off >= rootmap->alloc_offset) { 306 panic("hammer_blockmap_lookup: %016llx beyond EOF %016llx", 307 bmap_off, rootmap->alloc_offset); 308 goto done; 309 } 310 311 /* 312 * Dive layer 1. 313 */ 314 layer1_offset = rootmap->phys_offset + 315 HAMMER_BLOCKMAP_LAYER1_OFFSET(bmap_off); 316 layer1 = hammer_bread(trans->hmp, layer1_offset, &error, &buffer1); 317 KKASSERT(error == 0); 318 KKASSERT(layer1->phys_offset); 319 320 /* 321 * Dive layer 2, each entry represents a large-block. 322 */ 323 layer2_offset = layer1->phys_offset + 324 HAMMER_BLOCKMAP_LAYER2_OFFSET(bmap_off); 325 layer2 = hammer_bread(trans->hmp, layer2_offset, &error, &buffer2); 326 327 KKASSERT(error == 0); 328 KKASSERT(layer2->u.phys_offset); 329 hammer_modify_buffer(trans, buffer2, layer2, sizeof(*layer2)); 330 layer2->bytes_free += bytes; 331 KKASSERT(layer2->bytes_free <= HAMMER_LARGEBLOCK_SIZE); 332 333 /* 334 * If the big-block is free, return it to the free pool. If our 335 * iterator is in the wholely free block, leave the block intact 336 * and reset the iterator. 337 */ 338 if (layer2->bytes_free == HAMMER_LARGEBLOCK_SIZE) { 339 if ((rootmap->next_offset ^ bmap_off) & 340 ~HAMMER_LARGEBLOCK_MASK64) { 341 hammer_freemap_free(trans, layer2->u.phys_offset, 342 bmap_off, &error); 343 layer2->u.phys_offset = HAMMER_BLOCKMAP_FREE; 344 345 hammer_modify_buffer(trans, buffer1, 346 layer1, sizeof(*layer1)); 347 ++layer1->blocks_free; 348 #if 0 349 /* 350 * XXX Not working yet - we aren't clearing it when 351 * reallocating the block later on. 352 */ 353 if (layer1->blocks_free == HAMMER_BLOCKMAP_RADIX2) { 354 hammer_freemap_free( 355 trans, layer1->phys_offset, 356 bmap_off & ~HAMMER_BLOCKMAP_LAYER2_MASK, 357 &error); 358 layer1->phys_offset = HAMMER_BLOCKMAP_FREE; 359 } 360 #endif 361 hammer_modify_buffer_done(buffer1); 362 } else { 363 /* 364 * Leave block intact and reset the iterator. 365 * 366 * XXX can't do this yet because if we allow data 367 * allocations they could overwrite deleted data 368 * that is still subject to an undo on reboot. 369 */ 370 #if 0 371 hammer_modify_volume(trans, root_volume, 372 NULL, 0); 373 rootmap->next_offset &= ~HAMMER_LARGEBLOCK_MASK64; 374 hammer_modify_volume_done(root_volume); 375 #endif 376 } 377 } 378 hammer_modify_buffer_done(buffer2); 379 done: 380 lockmgr(&trans->hmp->blockmap_lock, LK_RELEASE); 381 382 if (buffer1) 383 hammer_rel_buffer(buffer1, 0); 384 if (buffer2) 385 hammer_rel_buffer(buffer2, 0); 386 hammer_rel_volume(root_volume, 0); 387 } 388 389 /* 390 * Return the number of free bytes in the big-block containing the 391 * specified blockmap offset. 392 */ 393 int 394 hammer_blockmap_getfree(hammer_mount_t hmp, hammer_off_t bmap_off, 395 int *curp, int *errorp) 396 { 397 hammer_volume_t root_volume; 398 hammer_blockmap_t rootmap; 399 struct hammer_blockmap_layer1 *layer1; 400 struct hammer_blockmap_layer2 *layer2; 401 hammer_buffer_t buffer = NULL; 402 hammer_off_t layer1_offset; 403 hammer_off_t layer2_offset; 404 int bytes; 405 int zone; 406 407 zone = HAMMER_ZONE_DECODE(bmap_off); 408 KKASSERT(zone >= HAMMER_ZONE_BTREE_INDEX && zone < HAMMER_MAX_ZONES); 409 root_volume = hammer_get_root_volume(hmp, errorp); 410 if (*errorp) { 411 *curp = 0; 412 return(0); 413 } 414 rootmap = &hmp->blockmap[zone]; 415 KKASSERT(rootmap->phys_offset != 0); 416 KKASSERT(HAMMER_ZONE_DECODE(rootmap->phys_offset) == 417 HAMMER_ZONE_RAW_BUFFER_INDEX); 418 KKASSERT(HAMMER_ZONE_DECODE(rootmap->alloc_offset) == zone); 419 420 if (bmap_off >= rootmap->alloc_offset) { 421 panic("hammer_blockmap_lookup: %016llx beyond EOF %016llx", 422 bmap_off, rootmap->alloc_offset); 423 bytes = 0; 424 *curp = 0; 425 goto done; 426 } 427 428 /* 429 * Dive layer 1. 430 */ 431 layer1_offset = rootmap->phys_offset + 432 HAMMER_BLOCKMAP_LAYER1_OFFSET(bmap_off); 433 layer1 = hammer_bread(hmp, layer1_offset, errorp, &buffer); 434 KKASSERT(*errorp == 0); 435 KKASSERT(layer1->phys_offset); 436 437 /* 438 * Dive layer 2, each entry represents a large-block. 439 */ 440 layer2_offset = layer1->phys_offset + 441 HAMMER_BLOCKMAP_LAYER2_OFFSET(bmap_off); 442 layer2 = hammer_bread(hmp, layer2_offset, errorp, &buffer); 443 444 KKASSERT(*errorp == 0); 445 KKASSERT(layer2->u.phys_offset); 446 447 bytes = layer2->bytes_free; 448 449 if ((rootmap->next_offset ^ bmap_off) & ~HAMMER_LARGEBLOCK_MASK64) 450 *curp = 0; 451 else 452 *curp = 1; 453 done: 454 if (buffer) 455 hammer_rel_buffer(buffer, 0); 456 hammer_rel_volume(root_volume, 0); 457 if (hammer_debug_general & 0x0800) { 458 kprintf("hammer_blockmap_getfree: %016llx -> %d\n", 459 bmap_off, bytes); 460 } 461 return(bytes); 462 } 463 464 465 /* 466 * Lookup a blockmap offset. 467 */ 468 hammer_off_t 469 hammer_blockmap_lookup(hammer_mount_t hmp, hammer_off_t bmap_off, int *errorp) 470 { 471 hammer_volume_t root_volume; 472 hammer_blockmap_t rootmap; 473 struct hammer_blockmap_layer1 *layer1; 474 struct hammer_blockmap_layer2 *layer2; 475 hammer_buffer_t buffer = NULL; 476 hammer_off_t layer1_offset; 477 hammer_off_t layer2_offset; 478 hammer_off_t result_offset; 479 int zone; 480 481 zone = HAMMER_ZONE_DECODE(bmap_off); 482 KKASSERT(zone >= HAMMER_ZONE_BTREE_INDEX && zone < HAMMER_MAX_ZONES); 483 root_volume = hammer_get_root_volume(hmp, errorp); 484 if (*errorp) 485 return(0); 486 rootmap = &hmp->blockmap[zone]; 487 KKASSERT(rootmap->phys_offset != 0); 488 KKASSERT(HAMMER_ZONE_DECODE(rootmap->phys_offset) == 489 HAMMER_ZONE_RAW_BUFFER_INDEX); 490 KKASSERT(HAMMER_ZONE_DECODE(rootmap->alloc_offset) == zone); 491 492 if (bmap_off >= rootmap->alloc_offset) { 493 panic("hammer_blockmap_lookup: %016llx beyond EOF %016llx", 494 bmap_off, rootmap->alloc_offset); 495 result_offset = 0; 496 goto done; 497 } 498 499 /* 500 * Dive layer 1. 501 */ 502 layer1_offset = rootmap->phys_offset + 503 HAMMER_BLOCKMAP_LAYER1_OFFSET(bmap_off); 504 layer1 = hammer_bread(hmp, layer1_offset, errorp, &buffer); 505 KKASSERT(*errorp == 0); 506 KKASSERT(layer1->phys_offset); 507 508 /* 509 * Dive layer 2, each entry represents a large-block. 510 */ 511 layer2_offset = layer1->phys_offset + 512 HAMMER_BLOCKMAP_LAYER2_OFFSET(bmap_off); 513 layer2 = hammer_bread(hmp, layer2_offset, errorp, &buffer); 514 515 KKASSERT(*errorp == 0); 516 KKASSERT(layer2->u.phys_offset); 517 518 result_offset = layer2->u.phys_offset + 519 (bmap_off & HAMMER_LARGEBLOCK_MASK64); 520 done: 521 if (buffer) 522 hammer_rel_buffer(buffer, 0); 523 hammer_rel_volume(root_volume, 0); 524 if (hammer_debug_general & 0x0800) { 525 kprintf("hammer_blockmap_lookup: %016llx -> %016llx\n", 526 bmap_off, result_offset); 527 } 528 return(result_offset); 529 } 530 531 /************************************************************************ 532 * IN-CORE TRACKING OF ALLOCATION HOLES * 533 ************************************************************************ 534 * 535 * This is a temporary shim in need of a more permanent solution. 536 * 537 * As we allocate space holes are created due to having to align to a new 538 * 16K buffer when an allocation would otherwise cross the buffer boundary. 539 * These holes are recorded here and used to fullfill smaller requests as 540 * much as possible. Only a limited number of holes are recorded and these 541 * functions operate somewhat like a heuristic, where information is allowed 542 * to be thrown away. 543 */ 544 545 void 546 hammer_init_holes(hammer_mount_t hmp, hammer_holes_t holes) 547 { 548 TAILQ_INIT(&holes->list); 549 holes->count = 0; 550 } 551 552 void 553 hammer_free_holes(hammer_mount_t hmp, hammer_holes_t holes) 554 { 555 hammer_hole_t hole; 556 557 while ((hole = TAILQ_FIRST(&holes->list)) != NULL) { 558 TAILQ_REMOVE(&holes->list, hole, entry); 559 kfree(hole, M_HAMMER); 560 } 561 } 562 563 /* 564 * Attempt to locate a hole with sufficient free space to accomodate the 565 * requested allocation. Return the offset or 0 if no hole could be found. 566 */ 567 static hammer_off_t 568 hammer_find_hole(hammer_mount_t hmp, hammer_holes_t holes, int bytes) 569 { 570 hammer_hole_t hole; 571 hammer_off_t result_off = 0; 572 573 TAILQ_FOREACH(hole, &holes->list, entry) { 574 if (bytes <= hole->bytes) { 575 result_off = hole->offset; 576 hole->offset += bytes; 577 hole->bytes -= bytes; 578 break; 579 } 580 } 581 return(result_off); 582 } 583 584 /* 585 * If a newly created hole is reasonably sized then record it. We only 586 * keep track of a limited number of holes. Lost holes are recovered by 587 * reblocking. 588 */ 589 static void 590 hammer_add_hole(hammer_mount_t hmp, hammer_holes_t holes, 591 hammer_off_t offset, int bytes) 592 { 593 hammer_hole_t hole; 594 595 if (bytes <= 128) 596 return; 597 598 if (holes->count < HAMMER_MAX_HOLES) { 599 hole = kmalloc(sizeof(*hole), M_HAMMER, M_WAITOK); 600 ++holes->count; 601 } else { 602 hole = TAILQ_FIRST(&holes->list); 603 TAILQ_REMOVE(&holes->list, hole, entry); 604 } 605 TAILQ_INSERT_TAIL(&holes->list, hole, entry); 606 hole->offset = offset; 607 hole->bytes = bytes; 608 } 609 610