dnode.c revision c543ec060d1359f6c8a9507242521f344a2ac3ef
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/*
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * CDDL HEADER START
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *
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 *
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * or http://www.opensolaris.org/os/licensing.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * See the License for the specific language governing permissions
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * and limitations under the License.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *
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 *
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * CDDL HEADER END
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/*
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Use is subject to license terms.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#pragma ident "%Z%%M% %I% %E% SMI"
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#include <sys/zfs_context.h>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#include <sys/dbuf.h>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#include <sys/dnode.h>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#include <sys/dmu.h>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#include <sys/dmu_impl.h>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#include <sys/dmu_tx.h>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#include <sys/dmu_objset.h>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#include <sys/dsl_dir.h>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#include <sys/dsl_dataset.h>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#include <sys/spa.h>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#include <sys/zio.h>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#include <sys/dmu_zfetch.h>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeestatic int free_range_compar(const void *node1, const void *node2);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeestatic kmem_cache_t *dnode_cache;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeestatic dnode_phys_t dnode_phys_zero;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeint zfs_default_bs = SPA_MINBLOCKSHIFT;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeint zfs_default_ibs = DN_MAX_INDBLKSHIFT;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/* ARGSUSED */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeestatic int
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_cons(void *arg, void *unused, int kmflag)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int i;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_t *dn = arg;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee bzero(dn, sizeof (dnode_t));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_init(&dn->dn_struct_rwlock, NULL, RW_DEFAULT, NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_init(&dn->dn_mtx, NULL, MUTEX_DEFAULT, NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_init(&dn->dn_dbufs_mtx, NULL, MUTEX_DEFAULT, NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee refcount_create(&dn->dn_holds);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee refcount_create(&dn->dn_tx_holds);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < TXG_SIZE; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee avl_create(&dn->dn_ranges[i], free_range_compar,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee sizeof (free_range_t),
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee offsetof(struct free_range, fr_node));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_create(&dn->dn_dirty_dbufs[i],
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee sizeof (dmu_buf_impl_t),
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee offsetof(dmu_buf_impl_t, db_dirty_node[i]));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_create(&dn->dn_dbufs, sizeof (dmu_buf_impl_t),
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee offsetof(dmu_buf_impl_t, db_link));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
127bbe13a6d36580af6a8ded154f1201a6250772tomee/* ARGSUSED */
127bbe13a6d36580af6a8ded154f1201a6250772tomeestatic void
127bbe13a6d36580af6a8ded154f1201a6250772tomeednode_dest(void *arg, void *unused)
127bbe13a6d36580af6a8ded154f1201a6250772tomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int i;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_t *dn = arg;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
127bbe13a6d36580af6a8ded154f1201a6250772tomee rw_destroy(&dn->dn_struct_rwlock);
127bbe13a6d36580af6a8ded154f1201a6250772tomee mutex_destroy(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_destroy(&dn->dn_dbufs_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee refcount_destroy(&dn->dn_holds);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee refcount_destroy(&dn->dn_tx_holds);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < TXG_SIZE; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee avl_destroy(&dn->dn_ranges[i]);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_destroy(&dn->dn_dirty_dbufs[i]);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_destroy(&dn->dn_dbufs);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
127bbe13a6d36580af6a8ded154f1201a6250772tomeednode_init(void)
127bbe13a6d36580af6a8ded154f1201a6250772tomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_cache = kmem_cache_create("dnode_t",
127bbe13a6d36580af6a8ded154f1201a6250772tomee sizeof (dnode_t),
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee 0, dnode_cons, dnode_dest, NULL, NULL, NULL, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_fini(void)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee kmem_cache_destroy(dnode_cache);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#ifdef ZFS_DEBUG
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_verify(dnode_t *dn)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int drop_struct_lock = FALSE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_phys);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_objset);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_phys->dn_type < DMU_OT_NUMTYPES);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (!(zfs_flags & ZFS_DEBUG_DNODE_VERIFY))
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (!RW_WRITE_HELD(&dn->dn_struct_rwlock)) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_enter(&dn->dn_struct_rwlock, RW_READER);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee drop_struct_lock = TRUE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_phys->dn_type != DMU_OT_NONE || dn->dn_allocated_txg != 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int i;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_indblkshift, >=, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_indblkshift, <=, SPA_MAXBLOCKSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_datablkshift) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_datablkshift, >=, SPA_MINBLOCKSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_datablkshift, <=, SPA_MAXBLOCKSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(1<<dn->dn_datablkshift, ==, dn->dn_datablksz);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_nlevels, <=, 30);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_type, <=, DMU_OT_NUMTYPES);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_nblkptr, >=, 1);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_nblkptr, <=, DN_MAX_NBLKPTR);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_bonuslen, <=, DN_MAX_BONUSLEN);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_datablksz, ==,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_datablkszsec << SPA_MINBLOCKSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(ISP2(dn->dn_datablksz), ==, dn->dn_datablkshift != 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U((dn->dn_nblkptr - 1) * sizeof (blkptr_t) +
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_bonuslen, <=, DN_MAX_BONUSLEN);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < TXG_SIZE; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_next_nlevels[i], <=, dn->dn_nlevels);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_phys->dn_type != DMU_OT_NONE)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_phys->dn_nlevels, <=, dn->dn_nlevels);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_object == DMU_META_DNODE_OBJECT || dn->dn_dbuf != NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_dbuf != NULL) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3P(dn->dn_phys, ==,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee (dnode_phys_t *)dn->dn_dbuf->db.db_data +
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee (dn->dn_object % (dn->dn_dbuf->db.db_size >> DNODE_SHIFT)));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (drop_struct_lock)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_exit(&dn->dn_struct_rwlock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#endif
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_byteswap(dnode_phys_t *dnp)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee uint64_t *buf64 = (void*)&dnp->dn_blkptr;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int i;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dnp->dn_type == DMU_OT_NONE) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee bzero(dnp, sizeof (dnode_phys_t));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnp->dn_type = BSWAP_8(dnp->dn_type);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnp->dn_indblkshift = BSWAP_8(dnp->dn_indblkshift);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnp->dn_nlevels = BSWAP_8(dnp->dn_nlevels);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnp->dn_nblkptr = BSWAP_8(dnp->dn_nblkptr);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnp->dn_bonustype = BSWAP_8(dnp->dn_bonustype);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnp->dn_checksum = BSWAP_8(dnp->dn_checksum);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnp->dn_compress = BSWAP_8(dnp->dn_compress);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnp->dn_datablkszsec = BSWAP_16(dnp->dn_datablkszsec);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnp->dn_bonuslen = BSWAP_16(dnp->dn_bonuslen);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnp->dn_maxblkid = BSWAP_64(dnp->dn_maxblkid);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnp->dn_secphys = BSWAP_64(dnp->dn_secphys);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
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 */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dnp->dn_indblkshift <= SPA_MAXBLOCKSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dnp->dn_nblkptr <= DN_MAX_NBLKPTR);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < dnp->dn_nblkptr * sizeof (blkptr_t)/8; i++)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee buf64[i] = BSWAP_64(buf64[i]);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
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 */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dnp->dn_bonuslen != 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
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 */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int off = (dnp->dn_nblkptr-1) * sizeof (blkptr_t);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee size_t len = DN_MAX_BONUSLEN - off;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_ot[dnp->dn_bonustype].ot_byteswap(dnp->dn_bonus + off, len);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_buf_byteswap(void *vbuf, size_t size)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_phys_t *buf = vbuf;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int i;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(sizeof (dnode_phys_t), ==, (1<<DNODE_SHIFT));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT((size & (sizeof (dnode_phys_t)-1)) == 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee size >>= DNODE_SHIFT;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < size; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_byteswap(buf);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee buf++;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeestatic int
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeefree_range_compar(const void *node1, const void *node2)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee const free_range_t *rp1 = node1;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee const free_range_t *rp2 = node2;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (rp1->fr_blkid < rp2->fr_blkid)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (-1);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee else if (rp1->fr_blkid > rp2->fr_blkid)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (1);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee else return (0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeestatic void
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_setdblksz(dnode_t *dn, int size)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(P2PHASE(size, SPA_MINBLOCKSIZE), ==, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(size, <=, SPA_MAXBLOCKSIZE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(size, >=, SPA_MINBLOCKSIZE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(size >> SPA_MINBLOCKSHIFT, <,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee 1<<(sizeof (dn->dn_phys->dn_datablkszsec) * 8));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_datablksz = size;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_datablkszsec = size >> SPA_MINBLOCKSHIFT;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_datablkshift = ISP2(size) ? highbit(size - 1) : 0;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeestatic dnode_t *
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_create(objset_impl_t *os, dnode_phys_t *dnp, dmu_buf_impl_t *db,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee uint64_t object)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_t *dn = kmem_cache_alloc(dnode_cache, KM_SLEEP);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee (void) dnode_cons(dn, NULL, 0); /* XXX */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_objset = os;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_object = object;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_dbuf = db;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_phys = dnp;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dnp->dn_datablkszsec)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_setdblksz(dn, dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_indblkshift = dnp->dn_indblkshift;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_nlevels = dnp->dn_nlevels;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_type = dnp->dn_type;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_nblkptr = dnp->dn_nblkptr;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_checksum = dnp->dn_checksum;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_compress = dnp->dn_compress;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_bonustype = dnp->dn_bonustype;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_bonuslen = dnp->dn_bonuslen;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_maxblkid = dnp->dn_maxblkid;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_zfetch_init(&dn->dn_zfetch, dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_phys->dn_type < DMU_OT_NUMTYPES);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&os->os_lock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_insert_head(&os->os_dnodes, dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&os->os_lock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeestatic void
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_destroy(dnode_t *dn)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee objset_impl_t *os = dn->dn_objset;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&os->os_lock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_remove(&os->os_dnodes, dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&os->os_lock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_dirtyctx_firstset) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee kmem_free(dn->dn_dirtyctx_firstset, 1);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_dirtyctx_firstset = NULL;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_zfetch_rele(&dn->dn_zfetch);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_bonus) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&dn->dn_bonus->db_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_evict(dn->dn_bonus);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_bonus = NULL;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee kmem_cache_free(dnode_cache, dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
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{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int i;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (blocksize == 0)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee blocksize = 1 << zfs_default_bs;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee else if (blocksize > SPA_MAXBLOCKSIZE)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee blocksize = SPA_MAXBLOCKSIZE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee else
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee blocksize = P2ROUNDUP(blocksize, SPA_MINBLOCKSIZE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (ibs == 0)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ibs = zfs_default_ibs;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ibs = MIN(MAX(ibs, DN_MIN_INDBLKSHIFT), DN_MAX_INDBLKSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dprintf("os=%p obj=%llu txg=%llu blocksize=%d ibs=%d\n", dn->dn_objset,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_object, tx->tx_txg, blocksize, ibs);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_type == DMU_OT_NONE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(bcmp(dn->dn_phys, &dnode_phys_zero, sizeof (dnode_phys_t)) == 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_phys->dn_type == DMU_OT_NONE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(ot != DMU_OT_NONE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(ot, <, DMU_OT_NUMTYPES);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT((bonustype == DMU_OT_NONE && bonuslen == 0) ||
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee (bonustype != DMU_OT_NONE && bonuslen != 0));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(bonustype, <, DMU_OT_NUMTYPES);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(bonuslen, <=, DN_MAX_BONUSLEN);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_type == DMU_OT_NONE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_maxblkid, ==, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_allocated_txg, ==, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_assigned_txg, ==, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(refcount_is_zero(&dn->dn_tx_holds));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(refcount_count(&dn->dn_holds), <=, 1);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3P(list_head(&dn->dn_dbufs), ==, NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < TXG_SIZE; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_next_nlevels[i], ==, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_next_indblkshift[i], ==, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_next_blksz[i], ==, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(!list_link_active(&dn->dn_dirty_link[i]));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3P(list_head(&dn->dn_dirty_dbufs[i]), ==, NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(avl_numnodes(&dn->dn_ranges[i]), ==, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_type = ot;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_setdblksz(dn, blocksize);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_indblkshift = ibs;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_nlevels = 1;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_bonustype = bonustype;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_bonuslen = bonuslen;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_checksum = ZIO_CHECKSUM_INHERIT;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_compress = ZIO_COMPRESS_INHERIT;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_dirtyctx = 0;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_free_txg = 0;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_dirtyctx_firstset) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee kmem_free(dn->dn_dirtyctx_firstset, 1);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_dirtyctx_firstset = NULL;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_allocated_txg = tx->tx_txg;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_setdirty(dn, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
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{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int i;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(blocksize, >=, SPA_MINBLOCKSIZE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(blocksize, <=, SPA_MAXBLOCKSIZE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(blocksize % SPA_MINBLOCKSIZE, ==, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_object != DMU_META_DNODE_OBJECT || dmu_tx_private_ok(tx));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(tx->tx_txg != 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT((bonustype == DMU_OT_NONE && bonuslen == 0) ||
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee (bonustype != DMU_OT_NONE && bonuslen != 0));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(bonustype, <, DMU_OT_NUMTYPES);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(bonuslen, <=, DN_MAX_BONUSLEN);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < TXG_SIZE; i++)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(!list_link_active(&dn->dn_dirty_link[i]));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* clean up any unreferenced dbufs */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_evict_dbufs(dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3P(list_head(&dn->dn_dbufs), ==, NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * XXX I should really have a generation number to tell if we
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * need to do this...
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (blocksize != dn->dn_datablksz ||
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_bonustype != bonustype || dn->dn_bonuslen != bonuslen) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* free all old data */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_free_range(dn, 0, -1ULL, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* change blocksize */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_setdblksz(dn, blocksize);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_setdirty(dn, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = blocksize;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_exit(&dn->dn_struct_rwlock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* change type */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_type = ot;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_bonuslen != bonuslen) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_buf_impl_t *db = NULL;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* change bonus size */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (bonuslen == 0)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee bonuslen = 1; /* XXX */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_bonus == NULL)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_bonus = dbuf_create_bonus(dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee db = dn->dn_bonus;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_exit(&dn->dn_struct_rwlock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (refcount_add(&db->db_holds, FTAG) == 1)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_add_ref(dn, db);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&db->db_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(db->db.db_size, ==, dn->dn_bonuslen);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(db->db.db_data != NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee db->db.db_size = bonuslen;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&db->db_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_dirty(db, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_rele(db, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* change bonus size and type */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_bonustype = bonustype;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_bonuslen = bonuslen;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_checksum = ZIO_CHECKSUM_INHERIT;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_compress = ZIO_COMPRESS_INHERIT;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_nblkptr, <=, DN_MAX_NBLKPTR);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_allocated_txg = tx->tx_txg;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_special_close(dnode_t *dn)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
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
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * dnode.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee while (refcount_count(&dn->dn_holds) > 0)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee delay(1);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_destroy(dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_t *
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_special_open(objset_impl_t *os, dnode_phys_t *dnp, uint64_t object)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_t *dn = dnode_create(os, dnp, NULL, object);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee DNODE_VERIFY(dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeestatic void
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_buf_pageout(dmu_buf_t *db, void *arg)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_t **children_dnodes = arg;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int i;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int epb = db->db_size >> DNODE_SHIFT;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < epb; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_t *dn = children_dnodes[i];
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int n;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn == NULL)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee continue;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#ifdef ZFS_DEBUG
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
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 */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(refcount_is_zero(&dn->dn_holds));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(list_head(&dn->dn_dbufs) == NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(refcount_is_zero(&dn->dn_tx_holds));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (n = 0; n < TXG_SIZE; n++)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(!list_link_active(&dn->dn_dirty_link[n]));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#endif
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee children_dnodes[i] = NULL;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_destroy(dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee kmem_free(children_dnodes, epb * sizeof (dnode_t *));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/*
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * errors:
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * EINVAL - invalid object number.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * EIO - i/o error.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * succeeds even for free dnodes.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeint
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_hold_impl(objset_impl_t *os, uint64_t object, int flag,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee void *tag, dnode_t **dnp)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int epb, idx, err;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int drop_struct_lock = FALSE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int type;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee uint64_t blk;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_t *mdn, *dn;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_buf_impl_t *db;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_t **children_dnodes;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (object == 0 || object >= DN_MAX_OBJECT)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (EINVAL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mdn = os->os_meta_dnode;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee DNODE_VERIFY(mdn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (!RW_WRITE_HELD(&mdn->dn_struct_rwlock)) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_enter(&mdn->dn_struct_rwlock, RW_READER);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee drop_struct_lock = TRUE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee blk = dbuf_whichblock(mdn, object * sizeof (dnode_phys_t));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee db = dbuf_hold(mdn, blk, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (drop_struct_lock)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_exit(&mdn->dn_struct_rwlock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (db == NULL)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (EIO);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee err = dbuf_read(db, NULL, DB_RF_CANFAIL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (err) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_rele(db, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (err);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(db->db.db_size, >=, 1<<DNODE_SHIFT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee epb = db->db.db_size >> DNODE_SHIFT;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee idx = object & (epb-1);
127bbe13a6d36580af6a8ded154f1201a6250772tomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee children_dnodes = dmu_buf_get_user(&db->db);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (children_dnodes == NULL) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_t **winner;
127bbe13a6d36580af6a8ded154f1201a6250772tomee children_dnodes = kmem_zalloc(epb * sizeof (dnode_t *),
127bbe13a6d36580af6a8ded154f1201a6250772tomee KM_SLEEP);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (winner = dmu_buf_set_user(&db->db, children_dnodes, NULL,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_buf_pageout)) {
127bbe13a6d36580af6a8ded154f1201a6250772tomee kmem_free(children_dnodes, epb * sizeof (dnode_t *));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee children_dnodes = winner;
127bbe13a6d36580af6a8ded154f1201a6250772tomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if ((dn = children_dnodes[idx]) == NULL) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_t *winner;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn = dnode_create(os, (dnode_phys_t *)db->db.db_data+idx,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee db, object);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee winner = atomic_cas_ptr(&children_dnodes[idx], NULL, dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (winner != NULL) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_destroy(dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn = winner;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee type = dn->dn_type;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_free_txg ||
127bbe13a6d36580af6a8ded154f1201a6250772tomee ((flag & DNODE_MUST_BE_ALLOCATED) && type == DMU_OT_NONE) ||
127bbe13a6d36580af6a8ded154f1201a6250772tomee ((flag & DNODE_MUST_BE_FREE) && type != DMU_OT_NONE)) {
127bbe13a6d36580af6a8ded154f1201a6250772tomee mutex_exit(&dn->dn_mtx);
127bbe13a6d36580af6a8ded154f1201a6250772tomee dbuf_rele(db, FTAG);
127bbe13a6d36580af6a8ded154f1201a6250772tomee return (type == DMU_OT_NONE ? ENOENT : EEXIST);
127bbe13a6d36580af6a8ded154f1201a6250772tomee }
127bbe13a6d36580af6a8ded154f1201a6250772tomee mutex_exit(&dn->dn_mtx);
127bbe13a6d36580af6a8ded154f1201a6250772tomee
127bbe13a6d36580af6a8ded154f1201a6250772tomee if (refcount_add(&dn->dn_holds, tag) == 1)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_add_ref(db, dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee DNODE_VERIFY(dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3P(dn->dn_dbuf, ==, db);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(dn->dn_object, ==, object);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_rele(db, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *dnp = dn;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/*
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Return held dnode if the object is allocated, NULL if not.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeint
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_hold(objset_impl_t *os, uint64_t object, void *tag, dnode_t **dnp)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (dnode_hold_impl(os, object, DNODE_MUST_BE_ALLOCATED, tag, dnp));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_add_ref(dnode_t *dn, void *tag)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(refcount_count(&dn->dn_holds) > 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee (void) refcount_add(&dn->dn_holds, tag);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_rele(dnode_t *dn, void *tag)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee uint64_t refs;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee refs = refcount_remove(&dn->dn_holds, tag);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* NOTE: the DNODE_DNODE does not have a dn_dbuf */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (refs == 0 && dn->dn_dbuf)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_rele(dn->dn_dbuf, dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_setdirty(dnode_t *dn, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee objset_impl_t *os = dn->dn_objset;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee uint64_t txg = tx->tx_txg;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_object == DMU_META_DNODE_OBJECT)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee DNODE_VERIFY(dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#ifdef ZFS_DEBUG
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_phys->dn_type || dn->dn_allocated_txg);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* ASSERT(dn->dn_free_txg == 0 || dn->dn_free_txg >= txg); */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee#endif
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&os->os_lock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * If we are already marked dirty, we're done.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (list_link_active(&dn->dn_dirty_link[txg & TXG_MASK])) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&os->os_lock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(!refcount_is_zero(&dn->dn_holds) || list_head(&dn->dn_dbufs));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_datablksz != 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dprintf_ds(os->os_dsl_dataset, "obj=%llu txg=%llu\n",
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_object, txg);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_free_txg > 0 && dn->dn_free_txg <= txg) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_insert_tail(&os->os_free_dnodes[txg&TXG_MASK], dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_insert_tail(&os->os_dirty_dnodes[txg&TXG_MASK], dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&os->os_lock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
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 */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_add_ref(dn, (void *)(uintptr_t)tx->tx_txg);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_dirty(dn->dn_dbuf, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dsl_dataset_dirty(os->os_dsl_dataset, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_free(dnode_t *dn, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int txgoff = tx->tx_txg & TXG_MASK;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dprintf("dn=%p txg=%llu\n", dn, tx->tx_txg);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* we should be the only holder... hopefully */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* ASSERT3U(refcount_count(&dn->dn_holds), ==, 1); */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_type == DMU_OT_NONE || dn->dn_free_txg) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_free_txg = tx->tx_txg;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * If the dnode is already dirty, it needs to be moved from
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * the dirty list to the free list.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&dn->dn_objset->os_lock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (list_link_active(&dn->dn_dirty_link[txgoff])) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_remove(&dn->dn_objset->os_dirty_dnodes[txgoff], dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee list_insert_tail(&dn->dn_objset->os_free_dnodes[txgoff], dn);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&dn->dn_objset->os_lock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&dn->dn_objset->os_lock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_setdirty(dn, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/*
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
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeint
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_set_blksz(dnode_t *dn, uint64_t size, int ibs, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_buf_impl_t *db, *db_next;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int have_db0 = FALSE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int err = ENOTSUP;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (size == 0)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee size = SPA_MINBLOCKSIZE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (size > SPA_MAXBLOCKSIZE)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee size = SPA_MAXBLOCKSIZE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee else
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee size = P2ROUNDUP(size, SPA_MINBLOCKSIZE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (ibs == 0)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ibs = dn->dn_indblkshift;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (size >> SPA_MINBLOCKSHIFT == dn->dn_datablkszsec &&
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ibs == dn->dn_indblkshift)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* Check for any allocated blocks beyond the first */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_phys->dn_maxblkid != 0)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee goto end;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&dn->dn_dbufs_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (db = list_head(&dn->dn_dbufs); db; db = db_next) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee db_next = list_next(&dn->dn_dbufs, db);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (db->db_blkid == 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee have_db0 = TRUE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else if (db->db_blkid != DB_BONUS_BLKID) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&dn->dn_dbufs_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee goto end;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&dn->dn_dbufs_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee db = NULL;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (!BP_IS_HOLE(&dn->dn_phys->dn_blkptr[0]) || have_db0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* obtain the old block */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee db = dbuf_hold(dn, 0, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_new_size(db, size, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_setdblksz(dn, size);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_indblkshift = ibs;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_setdirty(dn, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = size;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_next_indblkshift[tx->tx_txg&TXG_MASK] = ibs;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (db)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_rele(db, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee err = 0;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeend:
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_exit(&dn->dn_struct_rwlock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (err);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeuint64_t
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_max_nonzero_offset(dnode_t *dn)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_phys->dn_maxblkid == 0 &&
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee BP_IS_HOLE(&dn->dn_phys->dn_blkptr[0]))
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee else
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return ((dn->dn_phys->dn_maxblkid+1) * dn->dn_datablksz);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_new_blkid(dnode_t *dn, uint64_t blkid, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee uint64_t txgoff = tx->tx_txg & TXG_MASK;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int drop_struct_lock = FALSE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int epbs, new_nlevels;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee uint64_t sz;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(blkid != DB_BONUS_BLKID);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (!RW_WRITE_HELD(&dn->dn_struct_rwlock)) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee drop_struct_lock = TRUE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (blkid <= dn->dn_maxblkid)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee goto out;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_maxblkid = blkid;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Compute the number of levels necessary to support the new maxblkid.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee new_nlevels = 1;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (sz = dn->dn_nblkptr;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee sz <= blkid && sz >= dn->dn_nblkptr; sz <<= epbs)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee new_nlevels++;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (new_nlevels > dn->dn_nlevels) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int old_nlevels = dn->dn_nlevels;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_buf_impl_t *db;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_nlevels = new_nlevels;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(new_nlevels, >, dn->dn_next_nlevels[txgoff]);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_next_nlevels[txgoff] = new_nlevels;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* Dirty the left indirects. */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee db = dbuf_hold_level(dn, old_nlevels, 0, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_dirty(db, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_rele(db, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeout:
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (drop_struct_lock)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_exit(&dn->dn_struct_rwlock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_clear_range(dnode_t *dn, uint64_t blkid, uint64_t nblks, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee avl_tree_t *tree = &dn->dn_ranges[tx->tx_txg&TXG_MASK];
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee avl_index_t where;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee free_range_t *rp;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee free_range_t rp_tofind;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee uint64_t endblk = blkid + nblks;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(MUTEX_HELD(&dn->dn_mtx));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(nblks <= UINT64_MAX - blkid); /* no overflow */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dprintf_dnode(dn, "blkid=%llu nblks=%llu txg=%llu\n",
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee blkid, nblks, tx->tx_txg);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rp_tofind.fr_blkid = blkid;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rp = avl_find(tree, &rp_tofind, &where);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (rp == NULL)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rp = avl_nearest(tree, where, AVL_BEFORE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (rp == NULL)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rp = avl_nearest(tree, where, AVL_AFTER);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee while (rp && (rp->fr_blkid <= blkid + nblks)) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee uint64_t fr_endblk = rp->fr_blkid + rp->fr_nblks;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee free_range_t *nrp = AVL_NEXT(tree, rp);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (blkid <= rp->fr_blkid && endblk >= fr_endblk) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* clear this entire range */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee avl_remove(tree, rp);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee kmem_free(rp, sizeof (free_range_t));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else if (blkid <= rp->fr_blkid &&
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee endblk > rp->fr_blkid && endblk < fr_endblk) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* clear the beginning of this range */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rp->fr_blkid = endblk;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rp->fr_nblks = fr_endblk - endblk;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else if (blkid > rp->fr_blkid && blkid < fr_endblk &&
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee endblk >= fr_endblk) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* clear the end of this range */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rp->fr_nblks = blkid - rp->fr_blkid;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else if (blkid > rp->fr_blkid && endblk < fr_endblk) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* clear a chunk out of this range */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee free_range_t *new_rp =
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee kmem_alloc(sizeof (free_range_t), KM_SLEEP);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee new_rp->fr_blkid = endblk;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee new_rp->fr_nblks = fr_endblk - endblk;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee avl_insert_here(tree, new_rp, rp, AVL_AFTER);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rp->fr_nblks = blkid - rp->fr_blkid;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* there may be no overlap */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rp = nrp;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_free_range(dnode_t *dn, uint64_t off, uint64_t len, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_buf_impl_t *db;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee uint64_t start, objsize, blkid, nblks;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int blkshift, blksz, tail, head, epbs;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int trunc = FALSE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee blksz = dn->dn_datablksz;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee blkshift = dn->dn_datablkshift;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
127bbe13a6d36580af6a8ded154f1201a6250772tomee
127bbe13a6d36580af6a8ded154f1201a6250772tomee /* If the range is past the end of the file, this is a no-op */
127bbe13a6d36580af6a8ded154f1201a6250772tomee objsize = blksz * (dn->dn_maxblkid+1);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (off >= objsize)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee goto out;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (len == -1ULL) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee len = UINT64_MAX - off;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee trunc = TRUE;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * First, block align the region to free:
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_maxblkid == 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (off == 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee head = 0;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee head = blksz - off;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(head, >, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee start = off;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(ISP2(blksz));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee head = P2NPHASE(off, blksz);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee start = P2PHASE(off, blksz);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* zero out any partial block data at the start of the range */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (head) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(start + head, ==, blksz);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (len < head)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee head = len;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dbuf_hold_impl(dn, 0, dbuf_whichblock(dn, off), TRUE,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee FTAG, &db) == 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee caddr_t data;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* don't dirty if it isn't on disk and isn't dirty */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (db->db_dirtied ||
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee (db->db_blkptr && !BP_IS_HOLE(db->db_blkptr))) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_exit(&dn->dn_struct_rwlock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_will_dirty(db, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee data = db->db.db_data;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee bzero(data + start, head);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_rele(db, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee off += head;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee len -= head;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* If the range was less than one block, we are done */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (len == 0)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee goto out;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* If the remaining range is past the end of the file, we are done */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (off > dn->dn_maxblkid << blkshift)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee goto out;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (off + len == UINT64_MAX)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee tail = 0;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee else
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee tail = P2PHASE(len, blksz);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT3U(P2PHASE(off, blksz), ==, 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* zero out any partial block data at the end of the range */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (tail) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (len < tail)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee tail = len;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dbuf_hold_impl(dn, 0, dbuf_whichblock(dn, off+len),
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee TRUE, FTAG, &db) == 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* don't dirty if it isn't on disk and isn't dirty */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (db->db_dirtied ||
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee (db->db_blkptr && !BP_IS_HOLE(db->db_blkptr))) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_exit(&dn->dn_struct_rwlock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_will_dirty(db, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee bzero(db->db.db_data, tail);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_rele(db, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee len -= tail;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* If the range did not include a full block, we are done */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (len == 0)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee goto out;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* dirty the left indirects */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_nlevels > 1 && off != 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee db = dbuf_hold_level(dn, 1,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee (off - head) >> (blkshift + epbs), FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_will_dirty(db, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_rele(db, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* dirty the right indirects */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_nlevels > 1 && !trunc) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee db = dbuf_hold_level(dn, 1,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee (off + len + tail - 1) >> (blkshift + epbs), FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_will_dirty(db, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_rele(db, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Finally, add this range to the dnode range list, we
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * will finish up this free operation in the syncing phase.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(IS_P2ALIGNED(off, 1<<blkshift));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(off + len == UINT64_MAX || IS_P2ALIGNED(len, 1<<blkshift));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee blkid = off >> blkshift;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee nblks = len >> blkshift;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (trunc)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dn->dn_maxblkid = (blkid ? blkid - 1 : 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_clear_range(dn, blkid, nblks, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee free_range_t *rp, *found;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee avl_index_t where;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee avl_tree_t *tree = &dn->dn_ranges[tx->tx_txg&TXG_MASK];
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /* Add new range to dn_ranges */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rp = kmem_alloc(sizeof (free_range_t), KM_SLEEP);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rp->fr_blkid = blkid;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rp->fr_nblks = nblks;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee found = avl_find(tree, rp, &where);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(found == NULL);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee avl_insert(tree, rp, where);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dprintf_dnode(dn, "blkid=%llu nblks=%llu txg=%llu\n",
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee blkid, nblks, tx->tx_txg);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_free_range(dn, blkid, nblks, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_setdirty(dn, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeout:
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_exit(&dn->dn_struct_rwlock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/* return TRUE if this blkid was freed in a recent txg, or FALSE if it wasn't */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeuint64_t
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_block_freed(dnode_t *dn, uint64_t blkid)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee free_range_t range_tofind;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee void *dp = spa_get_dsl(dn->dn_objset->os_spa);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int i;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (blkid == DB_BONUS_BLKID)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (FALSE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
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 */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dp == NULL)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (FALSE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_free_txg)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (TRUE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
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 */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee range_tofind.fr_blkid = blkid;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_enter(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = 0; i < TXG_SIZE; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee free_range_t *range_found;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee avl_index_t idx;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee range_found = avl_find(&dn->dn_ranges[i], &range_tofind, &idx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (range_found) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(range_found->fr_nblks > 0);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee break;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee range_found = avl_nearest(&dn->dn_ranges[i], idx, AVL_BEFORE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (range_found &&
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee range_found->fr_blkid + range_found->fr_nblks > blkid)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee break;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutex_exit(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (i < TXG_SIZE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/* call from syncing context when we actually write/free space for this dnode */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_diduse_space(dnode_t *dn, int64_t space)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee uint64_t sectors;
127bbe13a6d36580af6a8ded154f1201a6250772tomee
127bbe13a6d36580af6a8ded154f1201a6250772tomee dprintf_dnode(dn, "dn=%p dnp=%p secphys=%llu space=%lld\n",
127bbe13a6d36580af6a8ded154f1201a6250772tomee dn, dn->dn_phys,
127bbe13a6d36580af6a8ded154f1201a6250772tomee (u_longlong_t)dn->dn_phys->dn_secphys,
127bbe13a6d36580af6a8ded154f1201a6250772tomee (longlong_t)space);
127bbe13a6d36580af6a8ded154f1201a6250772tomee
127bbe13a6d36580af6a8ded154f1201a6250772tomee ASSERT(P2PHASE(space, 1<<DEV_BSHIFT) == 0);
127bbe13a6d36580af6a8ded154f1201a6250772tomee
127bbe13a6d36580af6a8ded154f1201a6250772tomee mutex_enter(&dn->dn_mtx);
127bbe13a6d36580af6a8ded154f1201a6250772tomee if (space > 0) {
127bbe13a6d36580af6a8ded154f1201a6250772tomee sectors = space >> DEV_BSHIFT;
127bbe13a6d36580af6a8ded154f1201a6250772tomee ASSERT3U(dn->dn_phys->dn_secphys + sectors, >=,
127bbe13a6d36580af6a8ded154f1201a6250772tomee dn->dn_phys->dn_secphys);
127bbe13a6d36580af6a8ded154f1201a6250772tomee dn->dn_phys->dn_secphys += sectors;
127bbe13a6d36580af6a8ded154f1201a6250772tomee } else {
127bbe13a6d36580af6a8ded154f1201a6250772tomee sectors = -space >> DEV_BSHIFT;
127bbe13a6d36580af6a8ded154f1201a6250772tomee ASSERT3U(dn->dn_phys->dn_secphys, >=, sectors);
127bbe13a6d36580af6a8ded154f1201a6250772tomee dn->dn_phys->dn_secphys -= sectors;
127bbe13a6d36580af6a8ded154f1201a6250772tomee }
127bbe13a6d36580af6a8ded154f1201a6250772tomee mutex_exit(&dn->dn_mtx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/*
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).
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeevoid
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_willuse_space(dnode_t *dn, int64_t space, dmu_tx_t *tx)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee objset_impl_t *os = dn->dn_objset;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dsl_dataset_t *ds = os->os_dsl_dataset;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (space > 0)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee space = spa_get_asize(os->os_spa, space);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (ds)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dsl_dir_willuse_space(ds->ds_dir, space, tx);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_tx_willuse_space(tx, space);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeestatic int
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_next_offset_level(dnode_t *dn, boolean_t hole, uint64_t *offset,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int lvl, uint64_t blkfill)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dmu_buf_impl_t *db = NULL;
127bbe13a6d36580af6a8ded154f1201a6250772tomee void *data = NULL;
127bbe13a6d36580af6a8ded154f1201a6250772tomee uint64_t epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
127bbe13a6d36580af6a8ded154f1201a6250772tomee uint64_t epb = 1ULL << epbs;
127bbe13a6d36580af6a8ded154f1201a6250772tomee uint64_t minfill, maxfill;
127bbe13a6d36580af6a8ded154f1201a6250772tomee int i, error, span;
127bbe13a6d36580af6a8ded154f1201a6250772tomee
127bbe13a6d36580af6a8ded154f1201a6250772tomee dprintf("probing object %llu offset %llx level %d of %u\n",
127bbe13a6d36580af6a8ded154f1201a6250772tomee dn->dn_object, *offset, lvl, dn->dn_phys->dn_nlevels);
127bbe13a6d36580af6a8ded154f1201a6250772tomee
127bbe13a6d36580af6a8ded154f1201a6250772tomee if (lvl == dn->dn_phys->dn_nlevels) {
127bbe13a6d36580af6a8ded154f1201a6250772tomee error = 0;
127bbe13a6d36580af6a8ded154f1201a6250772tomee epb = dn->dn_phys->dn_nblkptr;
127bbe13a6d36580af6a8ded154f1201a6250772tomee data = dn->dn_phys->dn_blkptr;
127bbe13a6d36580af6a8ded154f1201a6250772tomee } else {
127bbe13a6d36580af6a8ded154f1201a6250772tomee uint64_t blkid = dbuf_whichblock(dn, *offset) >> (epbs * lvl);
127bbe13a6d36580af6a8ded154f1201a6250772tomee error = dbuf_hold_impl(dn, lvl, blkid, TRUE, FTAG, &db);
127bbe13a6d36580af6a8ded154f1201a6250772tomee if (error) {
127bbe13a6d36580af6a8ded154f1201a6250772tomee if (error == ENOENT)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (hole ? 0 : ESRCH);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (error);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee (void) dbuf_read(db, NULL,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee DB_RF_MUST_SUCCEED | DB_RF_HAVESTRUCT);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee data = db->db.db_data;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (lvl == 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dnode_phys_t *dnp = data;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee span = DNODE_SHIFT;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee ASSERT(dn->dn_type == DMU_OT_DNODE);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = (*offset >> span) & (blkfill - 1); i < blkfill; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (!dnp[i].dn_type == hole)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee break;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *offset += 1ULL << span;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (i == blkfill)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee error = ESRCH;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee blkptr_t *bp = data;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee span = (lvl - 1) * epbs + dn->dn_datablkshift;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee minfill = 0;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee maxfill = blkfill << ((lvl - 1) * epbs);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (hole)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee maxfill--;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee else
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee minfill++;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (i = (*offset >> span) & ((1ULL << epbs) - 1);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee i < epb; i++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (bp[i].blk_fill >= minfill &&
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee bp[i].blk_fill <= maxfill)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee break;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *offset += 1ULL << span;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (i >= epb)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee error = ESRCH;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (db)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee dbuf_rele(db, FTAG);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (error);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/*
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 *
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 *
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 *
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().
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeint
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeednode_next_offset(dnode_t *dn, boolean_t hole, uint64_t *offset,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int minlvl, uint64_t blkfill)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int lvl, maxlvl;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int error = 0;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee uint64_t initial_offset = *offset;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_enter(&dn->dn_struct_rwlock, RW_READER);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_phys->dn_nlevels == 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_exit(&dn->dn_struct_rwlock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (ESRCH);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (dn->dn_datablkshift == 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (*offset < dn->dn_datablksz) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (hole)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *offset = dn->dn_datablksz;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee error = ESRCH;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_exit(&dn->dn_struct_rwlock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (error);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee maxlvl = dn->dn_phys->dn_nlevels;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (lvl = minlvl; lvl <= maxlvl; lvl++) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee error = dnode_next_offset_level(dn, hole, offset, lvl, blkfill);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (error == 0)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee break;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee while (--lvl >= minlvl && error == 0)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee error = dnode_next_offset_level(dn, hole, offset, lvl, blkfill);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rw_exit(&dn->dn_struct_rwlock);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
127bbe13a6d36580af6a8ded154f1201a6250772tomee if (initial_offset > *offset)
127bbe13a6d36580af6a8ded154f1201a6250772tomee return (ESRCH);
127bbe13a6d36580af6a8ded154f1201a6250772tomee
127bbe13a6d36580af6a8ded154f1201a6250772tomee return (error);
127bbe13a6d36580af6a8ded154f1201a6250772tomee}
127bbe13a6d36580af6a8ded154f1201a6250772tomee