* Iterate through the space map, invoking the callback on each (non-debug) * space map entry. Stop after reading 'end' bytes of the space map. */
| 83 | * space map entry. Stop after reading 'end' bytes of the space map. |
| 84 | */ |
| 85 | int |
| 86 | space_map_iterate(space_map_t *sm, uint64_t end, sm_cb_t callback, void *arg) |
| 87 | { |
| 88 | uint64_t blksz = sm->sm_blksz; |
| 89 | |
| 90 | ASSERT3U(blksz, !=, 0); |
| 91 | ASSERT3U(end, <=, space_map_length(sm)); |
| 92 | ASSERT0(P2PHASE(end, sizeof (uint64_t))); |
| 93 | |
| 94 | dmu_prefetch(sm->sm_os, space_map_object(sm), 0, 0, end, |
| 95 | ZIO_PRIORITY_SYNC_READ); |
| 96 | |
| 97 | int error = 0; |
| 98 | uint64_t txg = 0, sync_pass = 0; |
| 99 | for (uint64_t block_base = 0; block_base < end && error == 0; |
| 100 | block_base += blksz) { |
| 101 | dmu_buf_t *db; |
| 102 | error = dmu_buf_hold(sm->sm_os, space_map_object(sm), |
| 103 | block_base, FTAG, &db, DMU_READ_PREFETCH); |
| 104 | if (error != 0) |
| 105 | return (error); |
| 106 | |
| 107 | uint64_t *block_start = db->db_data; |
| 108 | uint64_t block_length = MIN(end - block_base, blksz); |
| 109 | uint64_t *block_end = block_start + |
| 110 | (block_length / sizeof (uint64_t)); |
| 111 | |
| 112 | VERIFY0(P2PHASE(block_length, sizeof (uint64_t))); |
| 113 | VERIFY3U(block_length, !=, 0); |
| 114 | ASSERT3U(blksz, ==, db->db_size); |
| 115 | |
| 116 | for (uint64_t *block_cursor = block_start; |
| 117 | block_cursor < block_end && error == 0; block_cursor++) { |
| 118 | uint64_t e = *block_cursor; |
| 119 | |
| 120 | if (sm_entry_is_debug(e)) { |
| 121 | /* |
| 122 | * Debug entries are only needed to record the |
| 123 | * current TXG and sync pass if available. |
| 124 | * |
| 125 | * Note though that sometimes there can be |
| 126 | * debug entries that are used as padding |
| 127 | * at the end of space map blocks in-order |
| 128 | * to not split a double-word entry in the |
| 129 | * middle between two blocks. These entries |
| 130 | * have their TXG field set to 0 and we |
| 131 | * skip them without recording the TXG. |
| 132 | * [see comment in space_map_write_seg()] |
| 133 | */ |
| 134 | uint64_t e_txg = SM_DEBUG_TXG_DECODE(e); |
| 135 | if (e_txg != 0) { |
| 136 | txg = e_txg; |
| 137 | sync_pass = SM_DEBUG_SYNCPASS_DECODE(e); |
| 138 | } else { |
| 139 | ASSERT0(SM_DEBUG_SYNCPASS_DECODE(e)); |
| 140 | } |
| 141 | continue; |
| 142 | } |
no test coverage detected