fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Common Development and Distribution License (the "License").
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * or http://www.opensolaris.org/os/licensing.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/zfs_context.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dbuf.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dnode.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dmu.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dmu_tx.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dmu_objset.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dsl_dataset.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/spa.h>
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens#include <sys/range_tree.h>
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman#include <sys/zfeature.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensdnode_increase_indirection(dnode_t *dn, dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_impl_t *db;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee int txgoff = tx->tx_txg & TXG_MASK;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee int nblkptr = dn->dn_phys->dn_nblkptr;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee int old_toplvl = dn->dn_phys->dn_nlevels - 1;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee int new_level = dn->dn_next_nlevels[txgoff];
fa9e4066f08beec538e775443c5be79dd423fcabahrens int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee /* this dnode can't be paged out because it's dirty */
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(dn->dn_phys->dn_type != DMU_OT_NONE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(RW_WRITE_HELD(&dn->dn_struct_rwlock));
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee ASSERT(new_level > 1 && dn->dn_phys->dn_nlevels > 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens db = dbuf_hold_level(dn, dn->dn_phys->dn_nlevels, 0, FTAG);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ASSERT(db != NULL);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dn->dn_phys->dn_nlevels = new_level;
f82bfe17f53efa8e4aca04a764d0352539201fb5gw dprintf("os=%p obj=%llu, increase to %d\n", dn->dn_objset,
f82bfe17f53efa8e4aca04a764d0352539201fb5gw dn->dn_object, dn->dn_phys->dn_nlevels);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie /* transfer dnode's block pointers to new indirect block */
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie (void) dbuf_read(db, NULL, DB_RF_MUST_SUCCEED|DB_RF_HAVESTRUCT);
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie ASSERT(db->db.db_data);
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie ASSERT(arc_released(db->db_buf));
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie ASSERT3U(sizeof (blkptr_t) * nblkptr, <=, db->db.db_size);
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie bcopy(dn->dn_phys->dn_blkptr, db->db.db_data,
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie sizeof (blkptr_t) * nblkptr);
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie arc_buf_freeze(db->db_buf);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* set dbuf's parent pointers to new indirect buf */
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee for (i = 0; i < nblkptr; i++) {
e57a022b8f718889ffa92adbde47a8f08abcdb25Justin T. Gibbs dmu_buf_impl_t *child =
e57a022b8f718889ffa92adbde47a8f08abcdb25Justin T. Gibbs dbuf_find(dn->dn_objset, dn->dn_object, old_toplvl, i);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (child == NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson#ifdef DEBUG
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(child);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson ASSERT3P(DB_DNODE(child), ==, dn);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(child);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson#endif /* DEBUG */
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee if (child->db_parent && child->db_parent != dn->dn_dbuf) {
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee ASSERT(child->db_parent->db_level == db->db_level);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee ASSERT(child->db_blkptr !=
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee &dn->dn_phys->dn_blkptr[child->db_blkid]);
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_exit(&child->db_mtx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee ASSERT(child->db_parent == NULL ||
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee child->db_parent == dn->dn_dbuf);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee child->db_parent = db;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dbuf_add_ref(db, child);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee if (db->db.db_data)
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee child->db_blkptr = (blkptr_t *)db->db.db_data + i;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee else
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee child->db_blkptr = NULL;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dprintf_dbuf_bp(child, child->db_blkptr,
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee "changed db_blkptr to new indirect %s", "");
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_exit(&child->db_mtx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee bzero(dn->dn_phys->dn_blkptr, sizeof (blkptr_t) * nblkptr);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dbuf_rele(db, FTAG);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee rw_exit(&dn->dn_struct_rwlock);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossmanstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensfree_blocks(dnode_t *dn, blkptr_t *bp, int num, dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t bytesfreed = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee dprintf("ds=%p obj=%llx num=%d\n", ds, dn->dn_object, num);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman for (int i = 0; i < num; i++, bp++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (BP_IS_HOLE(bp))
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick bytesfreed += dsl_dataset_block_kill(ds, bp, tx, B_FALSE);
99653d4ee642c6528e88224f12409a5f23060994eschrock ASSERT3U(bytesfreed, <=, DN_USED_BYTES(dn->dn_phys));
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman /*
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman * Save some useful information on the holes being
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman * punched, including logical size, type, and indirection
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman * level. Retaining birth time enables detection of when
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman * holes are punched for reducing the number of free
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman * records transmitted during a zfs send.
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman */
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman uint64_t lsize = BP_GET_LSIZE(bp);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman dmu_object_type_t type = BP_GET_TYPE(bp);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman uint64_t lvl = BP_GET_LEVEL(bp);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee bzero(bp, sizeof (blkptr_t));
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman if (spa_feature_is_active(dn->dn_objset->os_spa,
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman SPA_FEATURE_HOLE_BIRTH)) {
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman BP_SET_LSIZE(bp, lsize);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman BP_SET_TYPE(bp, type);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman BP_SET_LEVEL(bp, lvl);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman BP_SET_BIRTH(bp, dmu_tx_get_txg(tx), 0);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_diduse_space(dn, -bytesfreed);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
9c9dc39aa72ac40bb2558d54adfa596d217135d9ek#ifdef ZFS_DEBUG
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensfree_verify(dmu_buf_impl_t *db, uint64_t start, uint64_t end, dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int off, num;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int i, err, epbs;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t txg = tx->tx_txg;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_t *dn;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
fa9e4066f08beec538e775443c5be79dd423fcabahrens off = start - (db->db_blkid * 1<<epbs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens num = end - start + 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT3U(off, >=, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT3U(num, >=, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT3U(db->db_level, >, 0);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson ASSERT3U(db->db.db_size, ==, 1 << dn->dn_phys->dn_indblkshift);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT3U(off+num, <=, db->db.db_size >> SPA_BLKPTRSHIFT);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(db->db_blkptr != NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = off; i < off+num; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t *buf;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_impl_t *child;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dbuf_dirty_record_t *dr;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee int j;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(db->db_level == 1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson rw_enter(&dn->dn_struct_rwlock, RW_READER);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson err = dbuf_hold_impl(dn, db->db_level-1,
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie (db->db_blkid << epbs) + i, TRUE, FALSE, FTAG, &child);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson rw_exit(&dn->dn_struct_rwlock);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (err == ENOENT)
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(err == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(child->db_level == 0);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dr = child->db_last_dirty;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee while (dr && dr->dr_txg > txg)
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dr = dr->dr_next;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee ASSERT(dr == NULL || dr->dr_txg == txg);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee /* data_old better be zeroed */
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee if (dr) {
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee buf = dr->dt.dl.dr_data->b_data;
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (j = 0; j < child->db.db_size >> 3; j++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (buf[j] != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens panic("freed data not zero: "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "child=%p i=%d off=%d num=%d\n",
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh (void *)child, i, off, num);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * db_data better be zeroed unless it's dirty in a
fa9e4066f08beec538e775443c5be79dd423fcabahrens * future txg.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_enter(&child->db_mtx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens buf = child->db.db_data;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (buf != NULL && child->db_state != DB_FILL &&
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee child->db_last_dirty == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (j = 0; j < child->db.db_size >> 3; j++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (buf[j] != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens panic("freed data not zero: "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "child=%p i=%d off=%d num=%d\n",
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh (void *)child, i, off, num);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_exit(&child->db_mtx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dbuf_rele(child, FTAG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(db);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
9c9dc39aa72ac40bb2558d54adfa596d217135d9ek#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossmanstatic void
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossmanfree_children(dmu_buf_impl_t *db, uint64_t blkid, uint64_t nblks,
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_t *dn;
fa9e4066f08beec538e775443c5be79dd423fcabahrens blkptr_t *bp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_impl_t *subdb;
1a01181fdc809f40c64d5c6881ae3e4521a9d9c7George Wilson uint64_t start, end, dbstart, dbend;
1a01181fdc809f40c64d5c6881ae3e4521a9d9c7George Wilson unsigned int epbs, shift, i;
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee /*
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee * There is a small possibility that this block will not be cached:
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee * 1 - if level > 1 and there are no children with level <= 1
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman * 2 - if this block was evicted since we read it from
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman * dmu_tx_hold_free().
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee */
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee if (db->db_state != DB_CACHED)
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee (void) dbuf_read(db, NULL, DB_RF_MUST_SUCCEED);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling dbuf_release_bp(db);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman bp = db->db.db_data;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
1a01181fdc809f40c64d5c6881ae3e4521a9d9c7George Wilson ASSERT3U(epbs, <, 31);
fa9e4066f08beec538e775443c5be79dd423fcabahrens shift = (db->db_level - 1) * epbs;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dbstart = db->db_blkid << epbs;
fa9e4066f08beec538e775443c5be79dd423fcabahrens start = blkid >> shift;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dbstart < start) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens bp += start - dbstart;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens start = dbstart;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens dbend = ((db->db_blkid + 1) << epbs) - 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens end = (blkid + nblks - 1) >> shift;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dbend <= end)
fa9e4066f08beec538e775443c5be79dd423fcabahrens end = dbend;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT3U(start, <=, end);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (db->db_level == 1) {
9c9dc39aa72ac40bb2558d54adfa596d217135d9ek FREE_VERIFY(db, start, end, tx);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman free_blocks(dn, bp, end-start+1, tx);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman } else {
1a01181fdc809f40c64d5c6881ae3e4521a9d9c7George Wilson for (uint64_t id = start; id <= end; id++, bp++) {
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman if (BP_IS_HOLE(bp))
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman continue;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman rw_enter(&dn->dn_struct_rwlock, RW_READER);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman VERIFY0(dbuf_hold_impl(dn, db->db_level - 1,
1a01181fdc809f40c64d5c6881ae3e4521a9d9c7George Wilson id, TRUE, FALSE, FTAG, &subdb));
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman rw_exit(&dn->dn_struct_rwlock);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman ASSERT3P(bp, ==, subdb->db_blkptr);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman free_children(subdb, blkid, nblks, tx);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman dbuf_rele(subdb, FTAG);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman /* If this whole block is free, free ourself too. */
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman for (i = 0, bp = db->db.db_data; i < 1 << epbs; i++, bp++) {
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman if (!BP_IS_HOLE(bp))
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman break;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman }
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman if (i == 1 << epbs) {
1a01181fdc809f40c64d5c6881ae3e4521a9d9c7George Wilson /*
1a01181fdc809f40c64d5c6881ae3e4521a9d9c7George Wilson * We only found holes. Grab the rwlock to prevent
1a01181fdc809f40c64d5c6881ae3e4521a9d9c7George Wilson * anybody from reading the blocks we're about to
1a01181fdc809f40c64d5c6881ae3e4521a9d9c7George Wilson * zero out.
1a01181fdc809f40c64d5c6881ae3e4521a9d9c7George Wilson */
1a01181fdc809f40c64d5c6881ae3e4521a9d9c7George Wilson rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman bzero(db->db.db_data, db->db.db_size);
1a01181fdc809f40c64d5c6881ae3e4521a9d9c7George Wilson rw_exit(&dn->dn_struct_rwlock);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman free_blocks(dn, db->db_blkptr, 1, tx);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman } else {
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman /*
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman * Partial block free; must be marked dirty so that it
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman * will be written out.
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman */
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman ASSERT(db->db_dirtycnt > 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(db);
6b4acc8bd9d480535a4d057e291dc7c049f664d9ahrens arc_buf_freeze(db->db_buf);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
f7170741490edba9d1d9c697c177c887172bc741Will Andrews * Traverse the indicated range of the provided file
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and "free" all the blocks contained there.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrensdnode_sync_free_range_impl(dnode_t *dn, uint64_t blkid, uint64_t nblks,
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens blkptr_t *bp = dn->dn_phys->dn_blkptr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int dnlevel = dn->dn_phys->dn_nlevels;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman boolean_t trunc = B_FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (blkid > dn->dn_phys->dn_maxblkid)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(dn->dn_phys->dn_maxblkid < UINT64_MAX);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman if (blkid + nblks > dn->dn_phys->dn_maxblkid) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens nblks = dn->dn_phys->dn_maxblkid - blkid + 1;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman trunc = B_TRUE;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* There are no indirect blocks in the object */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dnlevel == 1) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (blkid >= dn->dn_phys->dn_nblkptr) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* this range was never made persistent */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT3U(blkid + nblks, <=, dn->dn_phys->dn_nblkptr);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman free_blocks(dn, bp + blkid, nblks, tx);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman } else {
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman int shift = (dnlevel - 1) *
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman (dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman int start = blkid >> shift;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman int end = (blkid + nblks - 1) >> shift;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman dmu_buf_impl_t *db;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman ASSERT(start < dn->dn_phys->dn_nblkptr);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman bp += start;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman for (int i = start; i <= end; i++, bp++) {
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman if (BP_IS_HOLE(bp))
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman continue;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman rw_enter(&dn->dn_struct_rwlock, RW_READER);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman VERIFY0(dbuf_hold_impl(dn, dnlevel - 1, i,
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie TRUE, FALSE, FTAG, &db));
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman rw_exit(&dn->dn_struct_rwlock);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman free_children(db, blkid, nblks, tx);
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman dbuf_rele(db, FTAG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (trunc) {
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman dn->dn_phys->dn_maxblkid = blkid == 0 ? 0 : blkid - 1;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t off = (dn->dn_phys->dn_maxblkid + 1) *
fa9e4066f08beec538e775443c5be79dd423fcabahrens (dn->dn_phys->dn_datablkszsec << SPA_MINBLOCKSHIFT);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(off < dn->dn_phys->dn_maxblkid ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens dn->dn_phys->dn_maxblkid == 0 ||
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee dnode_next_offset(dn, 0, &off, 1, 1, 0) != 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrenstypedef struct dnode_sync_free_range_arg {
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens dnode_t *dsfra_dnode;
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens dmu_tx_t *dsfra_tx;
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens} dnode_sync_free_range_arg_t;
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrensstatic void
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrensdnode_sync_free_range(void *arg, uint64_t blkid, uint64_t nblks)
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens{
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens dnode_sync_free_range_arg_t *dsfra = arg;
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens dnode_t *dn = dsfra->dsfra_dnode;
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens mutex_exit(&dn->dn_mtx);
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens dnode_sync_free_range_impl(dn, blkid, nblks, dsfra->dsfra_tx);
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens mutex_enter(&dn->dn_mtx);
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens}
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock/*
f7170741490edba9d1d9c697c177c887172bc741Will Andrews * Try to kick all the dnode's dbufs out of the cache...
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
1934e92fc930c49429ad71a8ca97340f33227e78maybeevoid
1934e92fc930c49429ad71a8ca97340f33227e78maybeednode_evict_dbufs(dnode_t *dn)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs dmu_buf_impl_t db_marker;
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs dmu_buf_impl_t *db, *db_next;
c543ec060d1359f6c8a9507242521f344a2ac3efahrens
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs mutex_enter(&dn->dn_dbufs_mtx);
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs for (db = avl_first(&dn->dn_dbufs); db != NULL; db = db_next) {
c543ec060d1359f6c8a9507242521f344a2ac3efahrens
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson#ifdef DEBUG
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs DB_DNODE_ENTER(db);
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs ASSERT3P(DB_DNODE(db), ==, dn);
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs DB_DNODE_EXIT(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson#endif /* DEBUG */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs mutex_enter(&db->db_mtx);
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs if (db->db_state != DB_EVICTING &&
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs refcount_is_zero(&db->db_holds)) {
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs db_marker.db_level = db->db_level;
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs db_marker.db_blkid = db->db_blkid;
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs db_marker.db_state = DB_SEARCH;
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs avl_insert_here(&dn->dn_dbufs, &db_marker, db,
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs AVL_BEFORE);
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson dbuf_destroy(db);
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs db_next = AVL_NEXT(&dn->dn_dbufs, &db_marker);
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs avl_remove(&dn->dn_dbufs, &db_marker);
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs } else {
d2058105c61ec61df3a2dd3f839fed8c3fe7bfd6Justin T. Gibbs db->db_pending_evict = TRUE;
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs mutex_exit(&db->db_mtx);
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs db_next = AVL_NEXT(&dn->dn_dbufs, db);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs }
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs mutex_exit(&dn->dn_dbufs_mtx);
c543ec060d1359f6c8a9507242521f344a2ac3efahrens
cd485b49201b16c079663125308af274b6299e96Justin T. Gibbs dnode_evict_bonus(dn);
cd485b49201b16c079663125308af274b6299e96Justin T. Gibbs}
cd485b49201b16c079663125308af274b6299e96Justin T. Gibbs
cd485b49201b16c079663125308af274b6299e96Justin T. Gibbsvoid
cd485b49201b16c079663125308af274b6299e96Justin T. Gibbsdnode_evict_bonus(dnode_t *dn)
cd485b49201b16c079663125308af274b6299e96Justin T. Gibbs{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
d2058105c61ec61df3a2dd3f839fed8c3fe7bfd6Justin T. Gibbs if (dn->dn_bonus != NULL) {
d2058105c61ec61df3a2dd3f839fed8c3fe7bfd6Justin T. Gibbs if (refcount_is_zero(&dn->dn_bonus->db_holds)) {
d2058105c61ec61df3a2dd3f839fed8c3fe7bfd6Justin T. Gibbs mutex_enter(&dn->dn_bonus->db_mtx);
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson dbuf_destroy(dn->dn_bonus);
d2058105c61ec61df3a2dd3f839fed8c3fe7bfd6Justin T. Gibbs dn->dn_bonus = NULL;
d2058105c61ec61df3a2dd3f839fed8c3fe7bfd6Justin T. Gibbs } else {
d2058105c61ec61df3a2dd3f839fed8c3fe7bfd6Justin T. Gibbs dn->dn_bonus->db_pending_evict = TRUE;
d2058105c61ec61df3a2dd3f839fed8c3fe7bfd6Justin T. Gibbs }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock rw_exit(&dn->dn_struct_rwlock);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybeestatic void
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybeednode_undirty_dbufs(list_t *list)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dbuf_dirty_record_t *dr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee while (dr = list_head(list)) {
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dmu_buf_impl_t *db = dr->dr_dbuf;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee uint64_t txg = dr->dr_txg;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick if (db->db_level != 0)
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dnode_undirty_dbufs(&dr->dt.di.dr_children);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_enter(&db->db_mtx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* XXX - use dbuf_undirty()? */
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee list_remove(list, dr);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee ASSERT(db->db_last_dirty == dr);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee db->db_last_dirty = NULL;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee db->db_dirtycnt -= 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (db->db_level == 0) {
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum ASSERT(db->db_blkid == DMU_BONUS_BLKID ||
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dr->dt.dl.dr_data == db->db_buf);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dbuf_unoverride(dr);
d2b3cbbd7f3a37bc7c01b526d3eb312acd070423Jorgen Lundman } else {
d2b3cbbd7f3a37bc7c01b526d3eb312acd070423Jorgen Lundman mutex_destroy(&dr->dt.di.dr_mtx);
d2b3cbbd7f3a37bc7c01b526d3eb312acd070423Jorgen Lundman list_destroy(&dr->dt.di.dr_children);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee kmem_free(dr, sizeof (dbuf_dirty_record_t));
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dbuf_rele_and_unlock(db, (void *)(uintptr_t)txg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybeestatic void
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybeednode_sync_free(dnode_t *dn, dmu_tx_t *tx)
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee{
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee int txgoff = tx->tx_txg & TXG_MASK;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee ASSERT(dmu_tx_is_syncing(tx));
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee /*
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee * Our contents should have been freed in dnode_sync() by the
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee * free range record inserted by the caller of dnode_free().
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee */
fb09f5aad449c97fe309678f3f604982b563a96fMadhav Suresh ASSERT0(DN_USED_BYTES(dn->dn_phys));
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee ASSERT(BP_IS_HOLE(dn->dn_phys->dn_blkptr));
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dnode_undirty_dbufs(&dn->dn_dirty_records[txgoff]);
1934e92fc930c49429ad71a8ca97340f33227e78maybee dnode_evict_dbufs(dn);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * XXX - It would be nice to assert this, but we may still
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * have residual holds from async evictions from the arc...
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock *
55434c770c89aa1b84474f2559a106803511aba0ek * zfs_obj_to_path() also depends on this being
55434c770c89aa1b84474f2559a106803511aba0ek * commented out.
55434c770c89aa1b84474f2559a106803511aba0ek *
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * ASSERT3U(refcount_count(&dn->dn_holds), ==, 1);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Undirty next bits */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dn->dn_next_nlevels[txgoff] = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dn->dn_next_indblkshift[txgoff] = 0;
c543ec060d1359f6c8a9507242521f344a2ac3efahrens dn->dn_next_blksz[txgoff] = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* ASSERT(blkptrs are zero); */
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(dn->dn_phys->dn_type != DMU_OT_NONE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(dn->dn_type != DMU_OT_NONE);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(dn->dn_free_txg > 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dn->dn_allocated_txg != dn->dn_free_txg)
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman dmu_buf_will_dirty(&dn->dn_dbuf->db, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens bzero(dn->dn_phys, sizeof (dnode_phys_t));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_enter(&dn->dn_mtx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dn->dn_type = DMU_OT_NONE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dn->dn_maxblkid = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dn->dn_allocated_txg = 0;
758f6e0b258f20dcb5b772642e2a18b998ee7927gw dn->dn_free_txg = 0;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dn->dn_have_spill = B_FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_exit(&dn->dn_mtx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ASSERT(dn->dn_object != DMU_META_DNODE_OBJECT);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_rele(dn, (void *)(uintptr_t)tx->tx_txg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Now that we've released our hold, the dnode may
fa9e4066f08beec538e775443c5be79dd423fcabahrens * be evicted, so we musn't access it.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee * Write out the dnode's dirty buffers.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybeevoid
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybeednode_sync(dnode_t *dn, dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_phys_t *dnp = dn->dn_phys;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee int txgoff = tx->tx_txg & TXG_MASK;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee list_t *list = &dn->dn_dirty_records[txgoff];
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens static const dnode_phys_t zerodn = { 0 };
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum boolean_t kill_spill = B_FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(dmu_tx_is_syncing(tx));
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(dnp->dn_type != DMU_OT_NONE || dn->dn_allocated_txg);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens ASSERT(dnp->dn_type != DMU_OT_NONE ||
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens bcmp(dnp, &zerodn, DNODE_SIZE) == 0);
9c9dc39aa72ac40bb2558d54adfa596d217135d9ek DNODE_VERIFY(dn);
c543ec060d1359f6c8a9507242521f344a2ac3efahrens
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee ASSERT(dn->dn_dbuf == NULL || arc_released(dn->dn_dbuf->db_buf));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (dmu_objset_userused_enabled(dn->dn_objset) &&
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens !DMU_OBJECT_IS_SPECIAL(dn->dn_object)) {
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum mutex_enter(&dn->dn_mtx);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dn->dn_oldused = DN_USED_BYTES(dn->dn_phys);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dn->dn_oldflags = dn->dn_phys->dn_flags;
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens dn->dn_phys->dn_flags |= DNODE_FLAG_USERUSED_ACCOUNTED;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum mutex_exit(&dn->dn_mtx);
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum dmu_objset_userquota_get_ids(dn, B_FALSE, tx);
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens } else {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens /* Once we account for it, we should always account for it. */
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens ASSERT(!(dn->dn_phys->dn_flags &
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens DNODE_FLAG_USERUSED_ACCOUNTED));
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens }
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_enter(&dn->dn_mtx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dn->dn_allocated_txg == tx->tx_txg) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* The dnode is newly allocated or reallocated */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dnp->dn_type == DMU_OT_NONE) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* this is a first alloc, not a realloc */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnp->dn_nlevels = 1;
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee dnp->dn_nblkptr = dn->dn_nblkptr;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnp->dn_type = dn->dn_type;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnp->dn_bonustype = dn->dn_bonustype;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnp->dn_bonuslen = dn->dn_bonuslen;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee ASSERT(dnp->dn_nlevels > 1 ||
f676ed3419ae468da6c6831c143b0b54173e08d2ahrens BP_IS_HOLE(&dnp->dn_blkptr[0]) ||
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens BP_IS_EMBEDDED(&dnp->dn_blkptr[0]) ||
f676ed3419ae468da6c6831c143b0b54173e08d2ahrens BP_GET_LSIZE(&dnp->dn_blkptr[0]) ==
f676ed3419ae468da6c6831c143b0b54173e08d2ahrens dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens ASSERT(dnp->dn_nlevels < 2 ||
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens BP_IS_HOLE(&dnp->dn_blkptr[0]) ||
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens BP_GET_LSIZE(&dnp->dn_blkptr[0]) == 1 << dnp->dn_indblkshift);
f676ed3419ae468da6c6831c143b0b54173e08d2ahrens
2acef22db7808606888f8f92715629ff3ba555b9Matthew Ahrens if (dn->dn_next_type[txgoff] != 0) {
2acef22db7808606888f8f92715629ff3ba555b9Matthew Ahrens dnp->dn_type = dn->dn_type;
2acef22db7808606888f8f92715629ff3ba555b9Matthew Ahrens dn->dn_next_type[txgoff] = 0;
2acef22db7808606888f8f92715629ff3ba555b9Matthew Ahrens }
2acef22db7808606888f8f92715629ff3ba555b9Matthew Ahrens
2acef22db7808606888f8f92715629ff3ba555b9Matthew Ahrens if (dn->dn_next_blksz[txgoff] != 0) {
c543ec060d1359f6c8a9507242521f344a2ac3efahrens ASSERT(P2PHASE(dn->dn_next_blksz[txgoff],
fa9e4066f08beec538e775443c5be79dd423fcabahrens SPA_MINBLOCKSIZE) == 0);
f676ed3419ae468da6c6831c143b0b54173e08d2ahrens ASSERT(BP_IS_HOLE(&dnp->dn_blkptr[0]) ||
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee dn->dn_maxblkid == 0 || list_head(list) != NULL ||
347a31bcb38b51837caee115d3979d3a981cc099ahrens dn->dn_next_blksz[txgoff] >> SPA_MINBLOCKSHIFT ==
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens dnp->dn_datablkszsec ||
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens range_tree_space(dn->dn_free_ranges[txgoff]) != 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnp->dn_datablkszsec =
c543ec060d1359f6c8a9507242521f344a2ac3efahrens dn->dn_next_blksz[txgoff] >> SPA_MINBLOCKSHIFT;
c543ec060d1359f6c8a9507242521f344a2ac3efahrens dn->dn_next_blksz[txgoff] = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
2acef22db7808606888f8f92715629ff3ba555b9Matthew Ahrens if (dn->dn_next_bonuslen[txgoff] != 0) {
1934e92fc930c49429ad71a8ca97340f33227e78maybee if (dn->dn_next_bonuslen[txgoff] == DN_ZERO_BONUSLEN)
1934e92fc930c49429ad71a8ca97340f33227e78maybee dnp->dn_bonuslen = 0;
1934e92fc930c49429ad71a8ca97340f33227e78maybee else
1934e92fc930c49429ad71a8ca97340f33227e78maybee dnp->dn_bonuslen = dn->dn_next_bonuslen[txgoff];
1934e92fc930c49429ad71a8ca97340f33227e78maybee ASSERT(dnp->dn_bonuslen <= DN_MAX_BONUSLEN);
1934e92fc930c49429ad71a8ca97340f33227e78maybee dn->dn_next_bonuslen[txgoff] = 0;
1934e92fc930c49429ad71a8ca97340f33227e78maybee }
1934e92fc930c49429ad71a8ca97340f33227e78maybee
2acef22db7808606888f8f92715629ff3ba555b9Matthew Ahrens if (dn->dn_next_bonustype[txgoff] != 0) {
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden ASSERT(DMU_OT_IS_VALID(dn->dn_next_bonustype[txgoff]));
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dnp->dn_bonustype = dn->dn_next_bonustype[txgoff];
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dn->dn_next_bonustype[txgoff] = 0;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman boolean_t freeing_dnode = dn->dn_free_txg > 0 &&
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman dn->dn_free_txg <= tx->tx_txg;
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum /*
e6518318428d2be1962bf2d47fd83ebfe8cb2736Matthew Ahrens * Remove the spill block if we have been explicitly asked to
e6518318428d2be1962bf2d47fd83ebfe8cb2736Matthew Ahrens * remove it, or if the object is being removed.
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum */
e6518318428d2be1962bf2d47fd83ebfe8cb2736Matthew Ahrens if (dn->dn_rm_spillblk[txgoff] || freeing_dnode) {
e6518318428d2be1962bf2d47fd83ebfe8cb2736Matthew Ahrens if (dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum kill_spill = B_TRUE;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dn->dn_rm_spillblk[txgoff] = 0;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
2acef22db7808606888f8f92715629ff3ba555b9Matthew Ahrens if (dn->dn_next_indblkshift[txgoff] != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(dnp->dn_nlevels == 1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnp->dn_indblkshift = dn->dn_next_indblkshift[txgoff];
fa9e4066f08beec538e775443c5be79dd423fcabahrens dn->dn_next_indblkshift[txgoff] = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Just take the live (open-context) values for checksum and compress.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Strictly speaking it's a future leak, but nothing bad happens if we
fa9e4066f08beec538e775443c5be79dd423fcabahrens * start using the new checksum or compress algorithm a little early.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnp->dn_checksum = dn->dn_checksum;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnp->dn_compress = dn->dn_compress;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_exit(&dn->dn_mtx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (kill_spill) {
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman free_blocks(dn, &dn->dn_phys->dn_spill, 1, tx);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum mutex_enter(&dn->dn_mtx);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dnp->dn_flags &= ~DNODE_FLAG_SPILL_BLKPTR;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum mutex_exit(&dn->dn_mtx);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* process all the "freed" ranges in the file */
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens if (dn->dn_free_ranges[txgoff] != NULL) {
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens dnode_sync_free_range_arg_t dsfra;
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens dsfra.dsfra_dnode = dn;
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens dsfra.dsfra_tx = tx;
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee mutex_enter(&dn->dn_mtx);
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens range_tree_vacate(dn->dn_free_ranges[txgoff],
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens dnode_sync_free_range, &dsfra);
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens range_tree_destroy(dn->dn_free_ranges[txgoff]);
bf16b11e8deb633dd6c4296d46e92399d1582df4Matthew Ahrens dn->dn_free_ranges[txgoff] = NULL;
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee mutex_exit(&dn->dn_mtx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
1934e92fc930c49429ad71a8ca97340f33227e78maybee
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman if (freeing_dnode) {
af346df58864e8fe897b1ff1a3a4c12f9294391bNed Bass dn->dn_objset->os_freed_dnodes++;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dnode_sync_free(dn, tx);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e503a685964805f048b35c2a4e70e0638344f2b7George Wilson if (dn->dn_next_nlevels[txgoff]) {
e503a685964805f048b35c2a4e70e0638344f2b7George Wilson dnode_increase_indirection(dn, tx);
e503a685964805f048b35c2a4e70e0638344f2b7George Wilson dn->dn_next_nlevels[txgoff] = 0;
e503a685964805f048b35c2a4e70e0638344f2b7George Wilson }
e503a685964805f048b35c2a4e70e0638344f2b7George Wilson
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee if (dn->dn_next_nblkptr[txgoff]) {
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee /* this should only happen on a realloc */
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee ASSERT(dn->dn_allocated_txg == tx->tx_txg);
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee if (dn->dn_next_nblkptr[txgoff] > dnp->dn_nblkptr) {
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee /* zero the new blkptrs we are gaining */
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee bzero(dnp->dn_blkptr + dnp->dn_nblkptr,
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee sizeof (blkptr_t) *
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee (dn->dn_next_nblkptr[txgoff] - dnp->dn_nblkptr));
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee#ifdef ZFS_DEBUG
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee } else {
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee int i;
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee ASSERT(dn->dn_next_nblkptr[txgoff] < dnp->dn_nblkptr);
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee /* the blkptrs we are losing better be unallocated */
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee for (i = dn->dn_next_nblkptr[txgoff];
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee i < dnp->dn_nblkptr; i++)
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee ASSERT(BP_IS_HOLE(&dnp->dn_blkptr[i]));
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee#endif
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee }
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee mutex_enter(&dn->dn_mtx);
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee dnp->dn_nblkptr = dn->dn_next_nblkptr[txgoff];
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee dn->dn_next_nblkptr[txgoff] = 0;
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee mutex_exit(&dn->dn_mtx);
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee }
da03de9920a5a87150a121e9851479c6b3364d8aMark Maybee
46e1baa6cf6d5432f5fd231bb588df8f9570c858Matthew Ahrens dbuf_sync_list(list, dn->dn_phys->dn_nlevels - 1, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens if (!DMU_OBJECT_IS_SPECIAL(dn->dn_object)) {
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee ASSERT3P(list_head(list), ==, NULL);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dnode_rele(dn, (void *)(uintptr_t)tx->tx_txg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee /*
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee * Although we have dropped our reference to the dnode, it
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee * can't be evicted until its written, and we haven't yet
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee * initiated the IO for the dnode's dbuf.
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee */
fa9e4066f08beec538e775443c5be79dd423fcabahrens}