Deleted Added
full compact
22c22
< * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
---
> * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
162a163,197
> static void
> dmu_tx_count_indirects(dmu_tx_hold_t *txh, dmu_buf_impl_t *db,
> boolean_t freeable, dmu_buf_impl_t **history)
> {
> int i = db->db_level + 1;
> dnode_t *dn = db->db_dnode;
>
> if (i >= dn->dn_nlevels)
> return;
>
> db = db->db_parent;
> if (db == NULL) {
> uint64_t lvls = dn->dn_nlevels - i;
>
> txh->txh_space_towrite += lvls << dn->dn_indblkshift;
> return;
> }
>
> if (db != history[i]) {
> dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset;
> uint64_t space = 1ULL << dn->dn_indblkshift;
>
> freeable = (db->db_blkptr && (freeable ||
> dsl_dataset_block_freeable(ds, db->db_blkptr->blk_birth)));
> if (freeable)
> txh->txh_space_tooverwrite += space;
> else
> txh->txh_space_towrite += space;
> if (db->db_blkptr)
> txh->txh_space_tounref += space;
> history[i] = db;
> dmu_tx_count_indirects(txh, db, freeable, history);
> }
> }
>
179a215,218
> if (dn) {
> dmu_buf_impl_t *last[DN_MAX_LEVELS];
> int nlvls = dn->dn_nlevels;
> int delta;
181,184c220,223
< /*
< * For i/o error checking, read the first and last level-0
< * blocks (if they are not aligned), and all the level-1 blocks.
< */
---
> /*
> * For i/o error checking, read the first and last level-0
> * blocks (if they are not aligned), and all the level-1 blocks.
> */
186d224
< if (dn) {
188,190c226,234
< err = dmu_tx_check_ioerr(NULL, dn, 0, 0);
< if (err)
< goto out;
---
> delta = dn->dn_datablksz;
> start = (off < dn->dn_datablksz) ? 0 : 1;
> end = (off+len <= dn->dn_datablksz) ? 0 : 1;
> if (start == 0 && (off > 0 || len < dn->dn_datablksz)) {
> err = dmu_tx_check_ioerr(NULL, dn, 0, 0);
> if (err)
> goto out;
> delta -= off;
> }
214,217c258,260
< if (dn->dn_nlevels > 1) {
< start >>= dn->dn_indblkshift - SPA_BLKPTRSHIFT;
< end >>= dn->dn_indblkshift - SPA_BLKPTRSHIFT;
< for (i = start+1; i < end; i++) {
---
> if (nlvls > 1) {
> int shft = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
> for (i = (start>>shft)+1; i < end>>shft; i++) {
226a270
> delta = P2NPHASE(off, dn->dn_datablksz);
228d271
< }
230,239c273,278
< /*
< * If there's more than one block, the blocksize can't change,
< * so we can make a more precise estimate. Alternatively,
< * if the dnode's ibs is larger than max_ibs, always use that.
< * This ensures that if we reduce DN_MAX_INDBLKSHIFT,
< * the code will still work correctly on existing pools.
< */
< if (dn && (dn->dn_maxblkid != 0 || dn->dn_indblkshift > max_ibs)) {
< min_ibs = max_ibs = dn->dn_indblkshift;
< if (dn->dn_datablkshift != 0)
---
> if (dn->dn_maxblkid > 0) {
> /*
> * The blocksize can't change,
> * so we can make a more precise estimate.
> */
> ASSERT(dn->dn_datablkshift != 0);
240a280,333
> 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;
> }
263,270c356
< /*
< * If we increase the number of levels of indirection,
< * we'll need new blkid=0 indirect blocks. If start == 0,
< * we're already accounting for that blocks; and if end == 0,
< * we can't increase the number of levels beyond that.
< */
< if (start != 0 && end != 0)
< txh->txh_space_towrite += 1ULL << max_ibs;
---
> ASSERT3U(end, >=, start);
271a358,364
> if (start != 0) {
> /*
> * We also need a new blkid=0 indirect block
> * to reference any existing file data.
> */
> txh->txh_space_towrite += 1ULL << max_ibs;
> }
274,275d366
< ASSERT(txh->txh_space_towrite < 2 * DMU_MAX_ACCESS);
<
276a368,371
> if (txh->txh_space_towrite + txh->txh_space_tooverwrite >
> 2 * DMU_MAX_ACCESS)
> err = EFBIG;
>
292a388
> txh->txh_space_tounref += space;
536c632
< dmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int add, char *name)
---
> dmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int add, const char *name)
604,609c700,701
< /*
< * 3 blocks overwritten: target leaf, ptrtbl block, header block
< * 3 new blocks written if adding: new split leaf, 2 grown ptrtbl blocks
< */
< dmu_tx_count_write(txh, dn->dn_maxblkid * dn->dn_datablksz,
< (3 + (add ? 3 : 0)) << dn->dn_datablkshift);
---
> err = zap_count_write(&dn->dn_objset->os, dn->dn_object, name, add,
> &txh->txh_space_towrite, &txh->txh_space_tooverwrite);
617c709,712
< txh->txh_space_towrite += 3 << dn->dn_indblkshift;
---
> if (dn->dn_objset->os_dsl_dataset->ds_phys->ds_prev_snap_obj)
> txh->txh_space_towrite += 3 << dn->dn_indblkshift;
> else
> txh->txh_space_tooverwrite += 3 << dn->dn_indblkshift;