+
+ if (dn->dn_type == ot && dn->dn_datablksz == blocksize &&
+ dn->dn_bonustype == bonustype && dn->dn_bonuslen == bonuslen) {
+ /* nothing is changing, this is a noop */
+ dnode_rele(dn, FTAG);
+ return (0);
+ }
+
+ if (bonustype == DMU_OT_SA) {
+ nblkptr = 1;
+ } else {
+ nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
+ }
+
+ /*
+ * If we are losing blkptrs or changing the block size this must
+ * be a new file instance. We must clear out the previous file
+ * contents before we can change this type of metadata in the dnode.
+ */
+ if (dn->dn_nblkptr > nblkptr || dn->dn_datablksz != blocksize) {
+ err = dmu_free_long_range(os, object, 0, DMU_OBJECT_END);
+ if (err)
+ goto out;
+ }
+
+ tx = dmu_tx_create(os);
+ dmu_tx_hold_bonus(tx, object);
+ err = dmu_tx_assign(tx, TXG_WAIT);
+ if (err) {
+ dmu_tx_abort(tx);
+ goto out;
+ }
+