dnode_sync.c revision 0f6d88aded0d165f5954688a9b13bac76c38da84
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * CDDL HEADER START
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * The contents of this file are subject to the terms of the
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * Common Development and Distribution License (the "License").
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * You may not use this file except in compliance with the License.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * See the License for the specific language governing permissions
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * and limitations under the License.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * When distributing Covered Code, include this CDDL HEADER in each
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * If applicable, add the following below this CDDL HEADER, with the
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * fields enclosed by brackets "[]" replaced with your own identifying
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * information: Portions Copyright [yyyy] [name of copyright owner]
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * CDDL HEADER END
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* this dnode can't be paged out because it's dirty */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee db = dbuf_hold_level(dn, dn->dn_phys->dn_nlevels, 0, FTAG);
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee dprintf("os=%p obj=%llu, increase to %d\n", dn->dn_objset,
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* check for existing blkptrs in the dnode */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee for (i = 0; i < nblkptr; i++)
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee if (i != nblkptr) {
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* transfer dnode's block pointers to new indirect block */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee (void) dbuf_read(db, NULL, DB_RF_MUST_SUCCEED|DB_RF_HAVESTRUCT);
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee ASSERT3U(sizeof (blkptr_t) * nblkptr, <=, db->db.db_size);
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee /* set dbuf's parent pointers to new indirect buf */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee for (i = 0; i < nblkptr; i++) {
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee#endif /* DEBUG */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee if (child->db_parent && child->db_parent != dn->dn_dbuf) {
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee bzero(dn->dn_phys->dn_blkptr, sizeof (blkptr_t) * nblkptr);
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomeefree_blocks(dnode_t *dn, blkptr_t *bp, int num, dmu_tx_t *tx)
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee dprintf("ds=%p obj=%llx num=%d\n", ds, dn->dn_object, num);
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee bytesfreed += dsl_dataset_block_kill(ds, bp, tx, B_FALSE);
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * Save some useful information on the holes being
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * punched, including logical size, type, and indirection
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * level. Retaining birth time enables detection of when
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * holes are punched for reducing the number of free
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * records transmitted during a zfs send.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomeefree_verify(dmu_buf_impl_t *db, uint64_t start, uint64_t end, dmu_tx_t *tx)
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee ASSERT3U(db->db.db_size, ==, 1 << dn->dn_phys->dn_indblkshift);
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee ASSERT3U(off+num, <=, db->db.db_size >> SPA_BLKPTRSHIFT);
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* data_old better be zeroed */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee if (buf[j] != 0) {
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee "child=%p i=%d off=%d num=%d\n",
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * db_data better be zeroed unless it's dirty in a
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * future txg.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee if (buf[j] != 0) {
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee "child=%p i=%d off=%d num=%d\n",
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomeefree_children(dmu_buf_impl_t *db, uint64_t blkid, uint64_t nblks,
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * There is a small possibility that this block will not be cached:
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * 1 - if level > 1 and there are no children with level <= 1
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * 2 - if this block was evicted since we read it from
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * dmu_tx_hold_free().
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* If this whole block is free, free ourself too. */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee for (i = 0, bp = db->db.db_data; i < 1 << epbs; i++, bp++) {
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* didn't find any non-holes */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * Partial block free; must be marked dirty so that it
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * will be written out.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * Traverse the indicated range of the provided file
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * and "free" all the blocks contained there.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomeednode_sync_free_range_impl(dnode_t *dn, uint64_t blkid, uint64_t nblks,
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* There are no indirect blocks in the object */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* this range was never made persistent */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee dn->dn_phys->dn_maxblkid = blkid == 0 ? 0 : blkid - 1;
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomeednode_sync_free_range(void *arg, uint64_t blkid, uint64_t nblks)
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee dnode_sync_free_range_impl(dn, blkid, nblks, dsfra->dsfra_tx);
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * Try to kick all the dnode's dbufs out of the cache...
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee for (db = avl_first(&dn->dn_dbufs); db != NULL; db = db_next) {
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee#endif /* DEBUG */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * NB: we need to drop dn_dbufs_mtx between passes so
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * that any DB_EVICTING dbufs can make progress.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * Ideally, we would have some cv we could wait on, but
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * since we don't, just wait a bit to give the other
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * thread a chance to run.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee if (dn->dn_bonus && refcount_is_zero(&dn->dn_bonus->db_holds)) {
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* XXX - use dbuf_undirty()? */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * Our contents should have been freed in dnode_sync() by the
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee * free range record inserted by the caller of dnode_free().
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee * XXX - It would be nice to assert this, but we may still
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee * have residual holds from async evictions from the arc...
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee * zfs_obj_to_path() also depends on this being
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee * commented out.
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee * ASSERT3U(refcount_count(&dn->dn_holds), ==, 1);
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee /* Undirty next bits */
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee /* ASSERT(blkptrs are zero); */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * Now that we've released our hold, the dnode may
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * be evicted, so we musn't access it.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * Write out the dnode's dirty buffers.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee ASSERT(dnp->dn_type != DMU_OT_NONE || dn->dn_allocated_txg);
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee ASSERT(dn->dn_dbuf == NULL || arc_released(dn->dn_dbuf->db_buf));
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee dn->dn_phys->dn_flags |= DNODE_FLAG_USERUSED_ACCOUNTED;
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* Once we account for it, we should always account for it. */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* The dnode is newly allocated or reallocated */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* this is a first alloc, not a realloc */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee BP_GET_LSIZE(&dnp->dn_blkptr[0]) == 1 << dnp->dn_indblkshift);
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee ASSERT(DMU_OT_IS_VALID(dn->dn_next_bonustype[txgoff]));
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * We will either remove a spill block when a file is being removed
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * or we have been asked to remove it.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee ((dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) && freeing_dnode)) {
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee dnp->dn_indblkshift = dn->dn_next_indblkshift[txgoff];
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * Just take the live (open-context) values for checksum and compress.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * Strictly speaking it's a future leak, but nothing bad happens if we
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee * start using the new checksum or compress algorithm a little early.
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* process all the "freed" ranges in the file */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* this should only happen on a realloc */
23b5c241225a8ade2b6b9f06ebb891ee459e3b02tomee /* zero the new blkptrs we are gaining */
sizeof (blkptr_t) *
#ifdef ZFS_DEBUG