/* * Return (in *dsizep) the amount of space on the deadlist which is: * mintxg < blk_birth <= maxtxg */ int bplist_space_birthrange(bplist_t *bpl, uint64_t mintxg, uint64_t maxtxg, uint64_t *dsizep) { uint64_t size = 0; uint64_t itor = 0; blkptr_t bp; int err; /* * As an optimization, if they want the whole txg range, just * get bpl_bytes rather than iterating over the bps. */ if (mintxg < TXG_INITIAL && maxtxg == UINT64_MAX) { mutex_enter(&bpl->bpl_lock); err = bplist_hold(bpl); if (err == 0) *dsizep = bpl->bpl_phys->bpl_bytes; mutex_exit(&bpl->bpl_lock); return (err); } while ((err = bplist_iterate(bpl, &itor, &bp)) == 0) { if (bp.blk_birth > mintxg && bp.blk_birth <= maxtxg) { size += bp_get_dsize(dmu_objset_spa(bpl->bpl_mos), &bp); } } if (err == ENOENT) err = 0; *dsizep = size; return (err); }
int bplist_iterate(bplist_t *bpl, uint64_t *itorp, blkptr_t *bp) { uint64_t blk, off; blkptr_t *bparray; int err; mutex_enter(&bpl->bpl_lock); err = bplist_hold(bpl); if (err) { mutex_exit(&bpl->bpl_lock); return (err); } if (*itorp >= bpl->bpl_phys->bpl_entries) { mutex_exit(&bpl->bpl_lock); return (ENOENT); } blk = *itorp >> bpl->bpl_bpshift; off = P2PHASE(*itorp, 1ULL << bpl->bpl_bpshift); err = bplist_cache(bpl, blk); if (err) { mutex_exit(&bpl->bpl_lock); return (err); } bparray = bpl->bpl_cached_dbuf->db_data; *bp = bparray[off]; (*itorp)++; mutex_exit(&bpl->bpl_lock); return (0); }
int bplist_space(bplist_t *bpl, uint64_t *usedp, uint64_t *compp, uint64_t *uncompp) { uint64_t itor = 0, comp = 0, uncomp = 0; int err; blkptr_t bp; mutex_enter(&bpl->bpl_lock); err = bplist_hold(bpl); if (err) { mutex_exit(&bpl->bpl_lock); return (err); } *usedp = bpl->bpl_phys->bpl_bytes; if (bpl->bpl_havecomp) { *compp = bpl->bpl_phys->bpl_comp; *uncompp = bpl->bpl_phys->bpl_uncomp; } mutex_exit(&bpl->bpl_lock); if (!bpl->bpl_havecomp) { while ((err = bplist_iterate(bpl, &itor, &bp)) == 0) { comp += BP_GET_PSIZE(&bp); uncomp += BP_GET_UCSIZE(&bp); } if (err == ENOENT) err = 0; *compp = comp; *uncompp = uncomp; } return (err); }
boolean_t bplist_empty(bplist_t *bpl) { boolean_t rv; if (bpl->bpl_object == 0) return (B_TRUE); mutex_enter(&bpl->bpl_lock); VERIFY(0 == bplist_hold(bpl)); /* XXX */ rv = (bpl->bpl_phys->bpl_entries == 0); mutex_exit(&bpl->bpl_lock); return (rv); }
void bplist_vacate(bplist_t *bpl, dmu_tx_t *tx) { mutex_enter(&bpl->bpl_lock); ASSERT3P(bpl->bpl_queue, ==, NULL); VERIFY(0 == bplist_hold(bpl)); dmu_buf_will_dirty(bpl->bpl_dbuf, tx); VERIFY(0 == dmu_free_range(bpl->bpl_mos, bpl->bpl_object, 0, -1ULL, tx)); bpl->bpl_phys->bpl_entries = 0; bpl->bpl_phys->bpl_bytes = 0; if (bpl->bpl_havecomp) { bpl->bpl_phys->bpl_comp = 0; bpl->bpl_phys->bpl_uncomp = 0; } mutex_exit(&bpl->bpl_lock); }
int bplist_enqueue(bplist_t *bpl, const blkptr_t *bp, dmu_tx_t *tx) { uint64_t blk, off; blkptr_t *bparray; int err; ASSERT(!BP_IS_HOLE(bp)); mutex_enter(&bpl->bpl_lock); err = bplist_hold(bpl); if (err) return (err); blk = bpl->bpl_phys->bpl_entries >> bpl->bpl_bpshift; off = P2PHASE(bpl->bpl_phys->bpl_entries, 1ULL << bpl->bpl_bpshift); err = bplist_cache(bpl, blk); if (err) { mutex_exit(&bpl->bpl_lock); return (err); } dmu_buf_will_dirty(bpl->bpl_cached_dbuf, tx); bparray = bpl->bpl_cached_dbuf->db_data; bparray[off] = *bp; /* We never need the fill count. */ bparray[off].blk_fill = 0; /* The bplist will compress better if we can leave off the checksum */ if (!BP_GET_DEDUP(&bparray[off])) bzero(&bparray[off].blk_cksum, sizeof (bparray[off].blk_cksum)); dmu_buf_will_dirty(bpl->bpl_dbuf, tx); bpl->bpl_phys->bpl_entries++; bpl->bpl_phys->bpl_bytes += bp_get_dsize_sync(dmu_objset_spa(bpl->bpl_mos), bp); if (bpl->bpl_havecomp) { bpl->bpl_phys->bpl_comp += BP_GET_PSIZE(bp); bpl->bpl_phys->bpl_uncomp += BP_GET_UCSIZE(bp); } mutex_exit(&bpl->bpl_lock); return (0); }