* Find the next hole, data, or sparse region at or after *offset. * The value 'blkfill' tells us how many items we expect to find * in an L0 data block; this value is 1 for normal objects, * DNODES_PER_BLOCK for the meta dnode, and some fraction of * DNODES_PER_BLOCK when searching for sparse regions thereof. * * Examples: * * dnode_next_offset(dn, flags, offset, 1, 1, 0); * Finds the nex
| 2514 | * Used in dmu_object_alloc(). |
| 2515 | */ |
| 2516 | int |
| 2517 | dnode_next_offset(dnode_t *dn, int flags, uint64_t *offset, |
| 2518 | int minlvl, uint64_t blkfill, uint64_t txg) |
| 2519 | { |
| 2520 | uint64_t initial_offset = *offset; |
| 2521 | int lvl, maxlvl; |
| 2522 | int error = 0; |
| 2523 | |
| 2524 | if (!(flags & DNODE_FIND_HAVELOCK)) |
| 2525 | rw_enter(&dn->dn_struct_rwlock, RW_READER); |
| 2526 | |
| 2527 | if (dn->dn_phys->dn_nlevels == 0) { |
| 2528 | error = SET_ERROR(ESRCH); |
| 2529 | goto out; |
| 2530 | } |
| 2531 | |
| 2532 | if (dn->dn_datablkshift == 0) { |
| 2533 | if (*offset < dn->dn_datablksz) { |
| 2534 | if (flags & DNODE_FIND_HOLE) |
| 2535 | *offset = dn->dn_datablksz; |
| 2536 | } else { |
| 2537 | error = SET_ERROR(ESRCH); |
| 2538 | } |
| 2539 | goto out; |
| 2540 | } |
| 2541 | |
| 2542 | maxlvl = dn->dn_phys->dn_nlevels; |
| 2543 | |
| 2544 | for (lvl = minlvl; lvl <= maxlvl; lvl++) { |
| 2545 | error = dnode_next_offset_level(dn, |
| 2546 | flags, offset, lvl, blkfill, txg); |
| 2547 | if (error != ESRCH) |
| 2548 | break; |
| 2549 | } |
| 2550 | |
| 2551 | while (error == 0 && --lvl >= minlvl) { |
| 2552 | error = dnode_next_offset_level(dn, |
| 2553 | flags, offset, lvl, blkfill, txg); |
| 2554 | } |
| 2555 | |
| 2556 | /* |
| 2557 | * There's always a "virtual hole" at the end of the object, even |
| 2558 | * if all BP's which physically exist are non-holes. |
| 2559 | */ |
| 2560 | if ((flags & DNODE_FIND_HOLE) && error == ESRCH && txg == 0 && |
| 2561 | minlvl == 1 && blkfill == 1 && !(flags & DNODE_FIND_BACKWARDS)) { |
| 2562 | error = 0; |
| 2563 | } |
| 2564 | |
| 2565 | if (error == 0 && (flags & DNODE_FIND_BACKWARDS ? |
| 2566 | initial_offset < *offset : initial_offset > *offset)) |
| 2567 | error = SET_ERROR(ESRCH); |
| 2568 | out: |
| 2569 | if (!(flags & DNODE_FIND_HAVELOCK)) |
| 2570 | rw_exit(&dn->dn_struct_rwlock); |
| 2571 | |
| 2572 | return (error); |
| 2573 | } |
no test coverage detected