dnode.c revision c543ec060d1359f6c8a9507242521f344a2ac3ef
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * CDDL HEADER START
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * The contents of this file are subject to the terms of the
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Common Development and Distribution License (the "License").
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * You may not use this file except in compliance with the License.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * See the License for the specific language governing permissions
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * and limitations under the License.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * When distributing Covered Code, include this CDDL HEADER in each
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * If applicable, add the following below this CDDL HEADER, with the
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * fields enclosed by brackets "[]" replaced with your own identifying
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * information: Portions Copyright [yyyy] [name of copyright owner]
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * CDDL HEADER END
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Use is subject to license terms.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#pragma ident "%Z%%M% %I% %E% SMI"
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeestatic int free_range_compar(const void *node1, const void *node2);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/* ARGSUSED */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_init(&dn->dn_struct_rwlock, NULL, RW_DEFAULT, NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_init(&dn->dn_dbufs_mtx, NULL, MUTEX_DEFAULT, NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < TXG_SIZE; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (0);
127bbe13a6d36580af6a8ded154f1201a6250772tomee/* ARGSUSED */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < TXG_SIZE; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_phys->dn_type != DMU_OT_NONE || dn->dn_allocated_txg != 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(1<<dn->dn_datablkshift, ==, dn->dn_datablksz);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(ISP2(dn->dn_datablksz), ==, dn->dn_datablkshift != 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < TXG_SIZE; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_phys->dn_nlevels, <=, dn->dn_nlevels);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_object == DMU_META_DNODE_OBJECT || dn->dn_dbuf != NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee (dn->dn_object % (dn->dn_dbuf->db.db_size >> DNODE_SHIFT)));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnp->dn_datablkszsec = BSWAP_16(dnp->dn_datablkszsec);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * dn_nblkptr is only one byte, so it's OK to read it in either
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * byte order. We can't read dn_bouslen.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < dnp->dn_nblkptr * sizeof (blkptr_t)/8; i++)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * OK to check dn_bonuslen for zero, because it won't matter if
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * we have the wrong byte order. This is necessary because the
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * dnode dnode is smaller than a regular dnode.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Note that the bonus length calculated here may be
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * longer than the actual bonus buffer. This is because
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * we always put the bonus buffer after the last block
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * pointer (instead of packing it against the end of the
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * dnode buffer).
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_ot[dnp->dn_bonustype].ot_byteswap(dnp->dn_bonus + off, len);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(sizeof (dnode_phys_t), ==, (1<<DNODE_SHIFT));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < size; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeefree_range_compar(const void *node1, const void *node2)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (-1);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (1);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee else return (0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_datablkshift = ISP2(size) ? highbit(size - 1) : 0;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_create(objset_impl_t *os, dnode_phys_t *dnp, dmu_buf_impl_t *db,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_t *dn = kmem_cache_alloc(dnode_cache, KM_SLEEP);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_setdblksz(dn, dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ibs = MIN(MAX(ibs, DN_MIN_INDBLKSHIFT), DN_MAX_INDBLKSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dprintf("os=%p obj=%llu txg=%llu blocksize=%d ibs=%d\n", dn->dn_objset,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(bcmp(dn->dn_phys, &dnode_phys_zero, sizeof (dnode_phys_t)) == 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < TXG_SIZE; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3P(list_head(&dn->dn_dirty_dbufs[i]), ==, NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_object != DMU_META_DNODE_OBJECT || dmu_tx_private_ok(tx));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < TXG_SIZE; i++)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* clean up any unreferenced dbufs */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * XXX I should really have a generation number to tell if we
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * need to do this...
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_bonustype != bonustype || dn->dn_bonuslen != bonuslen) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* free all old data */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* change blocksize */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* change type */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* change bonus size */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* change bonus size and type */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Wait for final references to the dnode to clear. This can
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * only happen if the arc is asyncronously evicting state that
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * has a hold on this dnode while we are trying to evict this
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_special_open(objset_impl_t *os, dnode_phys_t *dnp, uint64_t object)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < epb; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * If there are holds on this dnode, then there should
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * be holds on the dnode's containing dbuf as well; thus
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * it wouldn't be eligable for eviction and this function
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * would not have been called.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (n = 0; n < TXG_SIZE; n++)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * EINVAL - invalid object number.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * EIO - i/o error.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * succeeds even for free dnodes.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_hold_impl(objset_impl_t *os, uint64_t object, int flag,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee blk = dbuf_whichblock(mdn, object * sizeof (dnode_phys_t));
127bbe13a6d36580af6a8ded154f1201a6250772tomee children_dnodes = kmem_zalloc(epb * sizeof (dnode_t *),
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (winner = dmu_buf_set_user(&db->db, children_dnodes, NULL,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn = dnode_create(os, (dnode_phys_t *)db->db.db_data+idx,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee winner = atomic_cas_ptr(&children_dnodes[idx], NULL, dn);
127bbe13a6d36580af6a8ded154f1201a6250772tomee ((flag & DNODE_MUST_BE_ALLOCATED) && type == DMU_OT_NONE) ||
127bbe13a6d36580af6a8ded154f1201a6250772tomee ((flag & DNODE_MUST_BE_FREE) && type != DMU_OT_NONE)) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Return held dnode if the object is allocated, NULL if not.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_hold(objset_impl_t *os, uint64_t object, void *tag, dnode_t **dnp)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (dnode_hold_impl(os, object, DNODE_MUST_BE_ALLOCATED, tag, dnp));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* NOTE: the DNODE_DNODE does not have a dn_dbuf */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* ASSERT(dn->dn_free_txg == 0 || dn->dn_free_txg >= txg); */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * If we are already marked dirty, we're done.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (list_link_active(&dn->dn_dirty_link[txg & TXG_MASK])) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(!refcount_is_zero(&dn->dn_holds) || list_head(&dn->dn_dbufs));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_insert_tail(&os->os_free_dnodes[txg&TXG_MASK], dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_insert_tail(&os->os_dirty_dnodes[txg&TXG_MASK], dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * The dnode maintains a hold on its containing dbuf as
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * long as there are holds on it. Each instantiated child
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * dbuf maintaines a hold on the dnode. When the last child
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * drops its hold, the dnode will drop its hold on the
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * containing dbuf. We add a "dirty hold" here so that the
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * dnode will hang around after we finish processing its
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * children.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* we should be the only holder... hopefully */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* ASSERT3U(refcount_count(&dn->dn_holds), ==, 1); */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * If the dnode is already dirty, it needs to be moved from
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * the dirty list to the free list.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_remove(&dn->dn_objset->os_dirty_dnodes[txgoff], dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_insert_tail(&dn->dn_objset->os_free_dnodes[txgoff], dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Try to change the block size for the indicated dnode. This can only
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * succeed if there are no blocks allocated or dirty beyond first block
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_set_blksz(dnode_t *dn, uint64_t size, int ibs, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (size >> SPA_MINBLOCKSHIFT == dn->dn_datablkszsec &&
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* Check for any allocated blocks beyond the first */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (db = list_head(&dn->dn_dbufs); db; db = db_next) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (!BP_IS_HOLE(&dn->dn_phys->dn_blkptr[0]) || have_db0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* obtain the old block */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return ((dn->dn_phys->dn_maxblkid+1) * dn->dn_datablksz);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_new_blkid(dnode_t *dn, uint64_t blkid, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Compute the number of levels necessary to support the new maxblkid.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(new_nlevels, >, dn->dn_next_nlevels[txgoff]);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* Dirty the left indirects. */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_clear_range(dnode_t *dn, uint64_t blkid, uint64_t nblks, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee avl_tree_t *tree = &dn->dn_ranges[tx->tx_txg&TXG_MASK];
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(nblks <= UINT64_MAX - blkid); /* no overflow */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* clear this entire range */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* clear the beginning of this range */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else if (blkid > rp->fr_blkid && blkid < fr_endblk &&
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* clear the end of this range */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else if (blkid > rp->fr_blkid && endblk < fr_endblk) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* clear a chunk out of this range */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* there may be no overlap */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_free_range(dnode_t *dn, uint64_t off, uint64_t len, dmu_tx_t *tx)
127bbe13a6d36580af6a8ded154f1201a6250772tomee /* If the range is past the end of the file, this is a no-op */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * First, block align the region to free:
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (off == 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* zero out any partial block data at the start of the range */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dbuf_hold_impl(dn, 0, dbuf_whichblock(dn, off), TRUE,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* don't dirty if it isn't on disk and isn't dirty */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* If the range was less than one block, we are done */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* If the remaining range is past the end of the file, we are done */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* zero out any partial block data at the end of the range */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dbuf_hold_impl(dn, 0, dbuf_whichblock(dn, off+len),
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* don't dirty if it isn't on disk and isn't dirty */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* If the range did not include a full block, we are done */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* dirty the left indirects */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* dirty the right indirects */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Finally, add this range to the dnode range list, we
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * will finish up this free operation in the syncing phase.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(off + len == UINT64_MAX || IS_P2ALIGNED(len, 1<<blkshift));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee avl_tree_t *tree = &dn->dn_ranges[tx->tx_txg&TXG_MASK];
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* Add new range to dn_ranges */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/* return TRUE if this blkid was freed in a recent txg, or FALSE if it wasn't */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * If we're in the process of opening the pool, dp will not be
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * set yet, but there shouldn't be anything dirty.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * If dn_datablkshift is not set, then there's only a single
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * block, in which case there will never be a free range so it
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * won't matter.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < TXG_SIZE; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee range_found = avl_find(&dn->dn_ranges[i], &range_tofind, &idx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee range_found = avl_nearest(&dn->dn_ranges[i], idx, AVL_BEFORE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee range_found->fr_blkid + range_found->fr_nblks > blkid)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (i < TXG_SIZE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/* call from syncing context when we actually write/free space for this dnode */
127bbe13a6d36580af6a8ded154f1201a6250772tomee dprintf_dnode(dn, "dn=%p dnp=%p secphys=%llu space=%lld\n",
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Call when we think we're going to write/free space in open context.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Be conservative (ie. OK to write less than this or free more than
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * this, but don't write more or free less).
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_willuse_space(dnode_t *dn, int64_t space, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_next_offset_level(dnode_t *dn, boolean_t hole, uint64_t *offset,
127bbe13a6d36580af6a8ded154f1201a6250772tomee uint64_t epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
127bbe13a6d36580af6a8ded154f1201a6250772tomee dprintf("probing object %llu offset %llx level %d of %u\n",
127bbe13a6d36580af6a8ded154f1201a6250772tomee dn->dn_object, *offset, lvl, dn->dn_phys->dn_nlevels);
127bbe13a6d36580af6a8ded154f1201a6250772tomee uint64_t blkid = dbuf_whichblock(dn, *offset) >> (epbs * lvl);
127bbe13a6d36580af6a8ded154f1201a6250772tomee error = dbuf_hold_impl(dn, lvl, blkid, TRUE, FTAG, &db);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (lvl == 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = (*offset >> span) & (blkfill - 1); i < blkfill; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee i < epb; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Find the next hole, data, or sparse region at or after *offset.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * The value 'blkfill' tells us how many items we expect to find
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * in an L0 data block; this value is 1 for normal objects,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * DNODES_PER_BLOCK for the meta dnode, and some fraction of
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * DNODES_PER_BLOCK when searching for sparse regions thereof.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Examples:
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * dnode_next_offset(dn, hole, offset, 1, 1);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Finds the next hole/data in a file.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Used in dmu_offset_next().
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * dnode_next_offset(mdn, hole, offset, 0, DNODES_PER_BLOCK);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Finds the next free/allocated dnode an objset's meta-dnode.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Used in dmu_object_next().
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * dnode_next_offset(mdn, TRUE, offset, 2, DNODES_PER_BLOCK >> 2);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Finds the next L2 meta-dnode bp that's at most 1/4 full.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Used in dmu_object_alloc().
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_next_offset(dnode_t *dn, boolean_t hole, uint64_t *offset,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee error = dnode_next_offset_level(dn, hole, offset, lvl, blkfill);