| 131 | } |
| 132 | |
| 133 | static void |
| 134 | free_blocks(dnode_t *dn, blkptr_t *bp, int num, dmu_tx_t *tx) |
| 135 | { |
| 136 | dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset; |
| 137 | uint64_t bytesfreed = 0; |
| 138 | |
| 139 | dprintf("ds=%p obj=%llx num=%d\n", ds, dn->dn_object, num); |
| 140 | |
| 141 | for (int i = 0; i < num; i++, bp++) { |
| 142 | if (BP_IS_HOLE(bp)) |
| 143 | continue; |
| 144 | |
| 145 | bytesfreed += dsl_dataset_block_kill(ds, bp, tx, B_FALSE); |
| 146 | ASSERT3U(bytesfreed, <=, DN_USED_BYTES(dn->dn_phys)); |
| 147 | |
| 148 | /* |
| 149 | * Save some useful information on the holes being |
| 150 | * punched, including logical size, type, and indirection |
| 151 | * level. Retaining birth time enables detection of when |
| 152 | * holes are punched for reducing the number of free |
| 153 | * records transmitted during a zfs send. |
| 154 | */ |
| 155 | |
| 156 | uint64_t lsize = BP_GET_LSIZE(bp); |
| 157 | dmu_object_type_t type = BP_GET_TYPE(bp); |
| 158 | uint64_t lvl = BP_GET_LEVEL(bp); |
| 159 | |
| 160 | bzero(bp, sizeof (blkptr_t)); |
| 161 | |
| 162 | if (spa_feature_is_active(dn->dn_objset->os_spa, |
| 163 | SPA_FEATURE_HOLE_BIRTH)) { |
| 164 | BP_SET_LSIZE(bp, lsize); |
| 165 | BP_SET_TYPE(bp, type); |
| 166 | BP_SET_LEVEL(bp, lvl); |
| 167 | BP_SET_BIRTH(bp, dmu_tx_get_txg(tx), 0); |
| 168 | } |
| 169 | } |
| 170 | dnode_diduse_space(dn, -bytesfreed); |
| 171 | } |
| 172 | |
| 173 | #ifdef ZFS_DEBUG |
| 174 | static void |
no test coverage detected