+ min_ibs = max_ibs = dn->dn_indblkshift;
+ } else if (dn->dn_indblkshift > max_ibs) {
+ /*
+ * This ensures that if we reduce DN_MAX_INDBLKSHIFT,
+ * the code will still work correctly on older pools.
+ */
+ min_ibs = max_ibs = dn->dn_indblkshift;
+ }
+
+ /*
+ * If this write is not off the end of the file
+ * we need to account for overwrites/unref.
+ */
+ if (start <= dn->dn_maxblkid)
+ bzero(last, sizeof (dmu_buf_impl_t *) * DN_MAX_LEVELS);
+ while (start <= dn->dn_maxblkid) {
+ spa_t *spa = txh->txh_tx->tx_pool->dp_spa;
+ dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset;
+ dmu_buf_impl_t *db;
+
+ rw_enter(&dn->dn_struct_rwlock, RW_READER);
+ db = dbuf_hold_level(dn, 0, start, FTAG);
+ rw_exit(&dn->dn_struct_rwlock);
+ if (db->db_blkptr && dsl_dataset_block_freeable(ds,
+ db->db_blkptr->blk_birth)) {
+ dprintf_bp(db->db_blkptr, "can free old%s", "");
+ txh->txh_space_tooverwrite += dn->dn_datablksz;
+ txh->txh_space_tounref += dn->dn_datablksz;
+ dmu_tx_count_indirects(txh, db, TRUE, last);
+ } else {
+ txh->txh_space_towrite += dn->dn_datablksz;
+ if (db->db_blkptr)
+ txh->txh_space_tounref +=
+ bp_get_dasize(spa, db->db_blkptr);
+ dmu_tx_count_indirects(txh, db, FALSE, last);
+ }
+ dbuf_rele(db, FTAG);
+ if (++start > end) {
+ /*
+ * Account for new indirects appearing
+ * before this IO gets assigned into a txg.
+ */
+ bits = 64 - min_bs;
+ epbs = min_ibs - SPA_BLKPTRSHIFT;
+ for (bits -= epbs * (nlvls - 1);
+ bits >= 0; bits -= epbs)
+ txh->txh_fudge += 1ULL << max_ibs;
+ goto out;
+ }
+ off += delta;
+ if (len >= delta)
+ len -= delta;
+ delta = dn->dn_datablksz;
+ }