static int dump_dnode(dmu_sendarg_t *dsp, uint64_t object, dnode_phys_t *dnp) { struct drr_object *drro = &(dsp->dsa_drr->drr_u.drr_object); if (dnp == NULL || dnp->dn_type == DMU_OT_NONE) return (dump_freeobjects(dsp, object, 1)); if (dsp->dsa_pending_op != PENDING_NONE) { if (dump_bytes(dsp, dsp->dsa_drr, sizeof (dmu_replay_record_t)) != 0) return (EINTR); dsp->dsa_pending_op = PENDING_NONE; } /* write an OBJECT record */ bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t)); dsp->dsa_drr->drr_type = DRR_OBJECT; drro->drr_object = object; drro->drr_type = dnp->dn_type; drro->drr_bonustype = dnp->dn_bonustype; drro->drr_blksz = dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT; drro->drr_bonuslen = dnp->dn_bonuslen; drro->drr_checksumtype = dnp->dn_checksum; drro->drr_compress = dnp->dn_compress; drro->drr_toguid = dsp->dsa_toguid; if (dump_bytes(dsp, dsp->dsa_drr, sizeof (dmu_replay_record_t)) != 0) return (EINTR); if (dump_bytes(dsp, DN_BONUS(dnp), P2ROUNDUP(dnp->dn_bonuslen, 8)) != 0) return (EINTR); /* free anything past the end of the file */ if (dump_free(dsp, object, (dnp->dn_maxblkid + 1) * (dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT), -1ULL)) return (EINTR); if (dsp->dsa_err) return (EINTR); return (0); }
void dmu_objset_do_userquota_callbacks(objset_impl_t *os, dmu_tx_t *tx) { dnode_t *dn; list_t *list = &os->os_synced_dnodes; ASSERTV(static const char zerobuf[DN_MAX_BONUSLEN] = {0}); ASSERT(list_head(list) == NULL || dmu_objset_userused_enabled(os)); while ((dn = list_head(list))) { dmu_object_type_t bonustype; ASSERT(!DMU_OBJECT_IS_SPECIAL(dn->dn_object)); ASSERT(dn->dn_oldphys); ASSERT(dn->dn_phys->dn_type == DMU_OT_NONE || dn->dn_phys->dn_flags & DNODE_FLAG_USERUSED_ACCOUNTED); /* Allocate the user/groupused objects if necessary. */ if (os->os_userused_dnode->dn_type == DMU_OT_NONE) { VERIFY(0 == zap_create_claim(&os->os, DMU_USERUSED_OBJECT, DMU_OT_USERGROUP_USED, DMU_OT_NONE, 0, tx)); VERIFY(0 == zap_create_claim(&os->os, DMU_GROUPUSED_OBJECT, DMU_OT_USERGROUP_USED, DMU_OT_NONE, 0, tx)); } /* * If the object was not previously * accounted, pretend that it was free. */ if (!(dn->dn_oldphys->dn_flags & DNODE_FLAG_USERUSED_ACCOUNTED)) { bzero(dn->dn_oldphys, sizeof (dnode_phys_t)); } /* * If the object was freed, use the previous bonustype. */ bonustype = dn->dn_phys->dn_bonustype ? dn->dn_phys->dn_bonustype : dn->dn_oldphys->dn_bonustype; ASSERT(dn->dn_phys->dn_type != 0 || (bcmp(DN_BONUS(dn->dn_phys), zerobuf, DN_MAX_BONUSLEN) == 0 && DN_USED_BYTES(dn->dn_phys) == 0)); ASSERT(dn->dn_oldphys->dn_type != 0 || (bcmp(DN_BONUS(dn->dn_oldphys), zerobuf, DN_MAX_BONUSLEN) == 0 && DN_USED_BYTES(dn->dn_oldphys) == 0)); used_cbs[os->os_phys->os_type](&os->os, bonustype, DN_BONUS(dn->dn_oldphys), DN_BONUS(dn->dn_phys), DN_USED_BYTES(dn->dn_oldphys), DN_USED_BYTES(dn->dn_phys), tx); /* * The mutex is needed here for interlock with dnode_allocate. */ mutex_enter(&dn->dn_mtx); zio_buf_free(dn->dn_oldphys, sizeof (dnode_phys_t)); dn->dn_oldphys = NULL; mutex_exit(&dn->dn_mtx); list_remove(list, dn); dnode_rele(dn, list); } }