usr/src/uts/common/fs/zfs/dnode.c
author eschrock
Mon, 30 Jan 2006 21:34:28 -0800
changeset 1354 81359ee1ee63
parent 873 adefbfa5f42d
child 1402 bfaffef2800c
permissions -rw-r--r--
6362672 import gets confused about overlapping slices 6364582 need to fixup paths if they've changed
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     1
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     2
 * CDDL HEADER START
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     3
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     7
 * with the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     8
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    12
 * and limitations under the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    13
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    19
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    20
 * CDDL HEADER END
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    21
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    22
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    24
 * Use is subject to license terms.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    25
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    26
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    28
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    29
#include <sys/zfs_context.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    30
#include <sys/dbuf.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    31
#include <sys/dnode.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    32
#include <sys/dmu.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    33
#include <sys/dmu_impl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    34
#include <sys/dmu_tx.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    35
#include <sys/dmu_objset.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    36
#include <sys/dsl_dir.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    37
#include <sys/dsl_dataset.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    38
#include <sys/spa.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    39
#include <sys/zio.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    40
#include <sys/dmu_zfetch.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    41
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    42
static int free_range_compar(const void *node1, const void *node2);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    43
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    44
static kmem_cache_t *dnode_cache;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    45
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    46
static dnode_phys_t dnode_phys_zero;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    47
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    48
int zfs_default_bs = SPA_MINBLOCKSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    49
int zfs_default_ibs = DN_MAX_INDBLKSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    50
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    51
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    52
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    53
dnode_cons(void *arg, void *unused, int kmflag)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    54
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    55
	int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    56
	dnode_t *dn = arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    57
	bzero(dn, sizeof (dnode_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    58
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    59
	rw_init(&dn->dn_struct_rwlock, NULL, RW_DEFAULT, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    60
	mutex_init(&dn->dn_mtx, NULL, MUTEX_DEFAULT, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    61
	mutex_init(&dn->dn_dbufs_mtx, NULL, MUTEX_DEFAULT, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    62
	refcount_create(&dn->dn_holds);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    63
	refcount_create(&dn->dn_tx_holds);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    64
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    65
	for (i = 0; i < TXG_SIZE; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    66
		avl_create(&dn->dn_ranges[i], free_range_compar,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    67
		    sizeof (free_range_t),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    68
		    offsetof(struct free_range, fr_node));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    69
		list_create(&dn->dn_dirty_dbufs[i],
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    70
		    sizeof (dmu_buf_impl_t),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    71
		    offsetof(dmu_buf_impl_t, db_dirty_node[i]));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    72
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    73
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    74
	list_create(&dn->dn_dbufs, sizeof (dmu_buf_impl_t),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    75
	    offsetof(dmu_buf_impl_t, db_link));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    76
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    77
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    78
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    79
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    80
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    81
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    82
dnode_dest(void *arg, void *unused)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    83
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    84
	int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    85
	dnode_t *dn = arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    86
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    87
	rw_destroy(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    88
	mutex_destroy(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    89
	mutex_destroy(&dn->dn_dbufs_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    90
	refcount_destroy(&dn->dn_holds);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    91
	refcount_destroy(&dn->dn_tx_holds);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    92
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    93
	for (i = 0; i < TXG_SIZE; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    94
		avl_destroy(&dn->dn_ranges[i]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    95
		list_destroy(&dn->dn_dirty_dbufs[i]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    96
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    97
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    98
	list_destroy(&dn->dn_dbufs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    99
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   100
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   101
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   102
dnode_init(void)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   103
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   104
	dnode_cache = kmem_cache_create("dnode_t",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   105
	    sizeof (dnode_t),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   106
	    0, dnode_cons, dnode_dest, NULL, NULL, NULL, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   107
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   108
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   109
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   110
dnode_fini(void)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   111
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   112
	kmem_cache_destroy(dnode_cache);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   113
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   114
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   115
873
adefbfa5f42d 6347448 non ZFS_DEBUG kernels shouldn't call empty verify functions
ek110237
parents: 789
diff changeset
   116
#ifdef ZFS_DEBUG
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   117
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   118
dnode_verify(dnode_t *dn)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   119
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   120
	int drop_struct_lock = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   121
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   122
	ASSERT(dn->dn_phys);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   123
	ASSERT(dn->dn_objset);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   124
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   125
	ASSERT(dn->dn_phys->dn_type < DMU_OT_NUMTYPES);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   126
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   127
	if (!(zfs_flags & ZFS_DEBUG_DNODE_VERIFY))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   128
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   129
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   130
	if (!RW_WRITE_HELD(&dn->dn_struct_rwlock)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   131
		rw_enter(&dn->dn_struct_rwlock, RW_READER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   132
		drop_struct_lock = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   133
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   134
	if (dn->dn_phys->dn_type != DMU_OT_NONE || dn->dn_allocated_txg != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   135
		int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   136
		ASSERT3U(dn->dn_indblkshift, >=, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   137
		ASSERT3U(dn->dn_indblkshift, <=, SPA_MAXBLOCKSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   138
		if (dn->dn_datablkshift) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   139
			ASSERT3U(dn->dn_datablkshift, >=, SPA_MINBLOCKSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   140
			ASSERT3U(dn->dn_datablkshift, <=, SPA_MAXBLOCKSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   141
			ASSERT3U(1<<dn->dn_datablkshift, ==, dn->dn_datablksz);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   142
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   143
		ASSERT3U(dn->dn_nlevels, <=, 30);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   144
		ASSERT3U(dn->dn_type, <=, DMU_OT_NUMTYPES);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   145
		ASSERT3U(dn->dn_nblkptr, >=, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   146
		ASSERT3U(dn->dn_nblkptr, <=, DN_MAX_NBLKPTR);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   147
		ASSERT3U(dn->dn_bonuslen, <=, DN_MAX_BONUSLEN);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   148
		ASSERT3U(dn->dn_datablksz, ==,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   149
		    dn->dn_datablkszsec << SPA_MINBLOCKSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   150
		ASSERT3U(ISP2(dn->dn_datablksz), ==, dn->dn_datablkshift != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   151
		ASSERT3U((dn->dn_nblkptr - 1) * sizeof (blkptr_t) +
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   152
		    dn->dn_bonuslen, <=, DN_MAX_BONUSLEN);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   153
		for (i = 0; i < TXG_SIZE; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   154
			ASSERT3U(dn->dn_next_nlevels[i], <=, dn->dn_nlevels);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   155
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   156
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   157
	if (dn->dn_phys->dn_type != DMU_OT_NONE)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   158
		ASSERT3U(dn->dn_phys->dn_nlevels, <=, dn->dn_nlevels);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   159
	ASSERT(IS_DNODE_DNODE(dn->dn_object) || dn->dn_dbuf);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   160
	if (dn->dn_dbuf != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   161
		ASSERT3P(dn->dn_phys, ==,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   162
		    (dnode_phys_t *)dn->dn_dbuf->db.db_data +
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   163
		    (dn->dn_object % (dn->dn_dbuf->db.db_size >> DNODE_SHIFT)));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   164
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   165
	if (drop_struct_lock)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   166
		rw_exit(&dn->dn_struct_rwlock);
873
adefbfa5f42d 6347448 non ZFS_DEBUG kernels shouldn't call empty verify functions
ek110237
parents: 789
diff changeset
   167
}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   168
#endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   169
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   170
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   171
dnode_byteswap(dnode_phys_t *dnp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   172
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   173
	uint64_t *buf64 = (void*)&dnp->dn_blkptr;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   174
	int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   175
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   176
	if (dnp->dn_type == DMU_OT_NONE) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   177
		bzero(dnp, sizeof (dnode_phys_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   178
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   179
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   180
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   181
	dnp->dn_type = BSWAP_8(dnp->dn_type);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   182
	dnp->dn_indblkshift = BSWAP_8(dnp->dn_indblkshift);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   183
	dnp->dn_nlevels = BSWAP_8(dnp->dn_nlevels);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   184
	dnp->dn_nblkptr = BSWAP_8(dnp->dn_nblkptr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   185
	dnp->dn_bonustype = BSWAP_8(dnp->dn_bonustype);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   186
	dnp->dn_checksum = BSWAP_8(dnp->dn_checksum);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   187
	dnp->dn_compress = BSWAP_8(dnp->dn_compress);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   188
	dnp->dn_datablkszsec = BSWAP_16(dnp->dn_datablkszsec);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   189
	dnp->dn_bonuslen = BSWAP_16(dnp->dn_bonuslen);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   190
	dnp->dn_maxblkid = BSWAP_64(dnp->dn_maxblkid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   191
	dnp->dn_secphys = BSWAP_64(dnp->dn_secphys);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   192
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   193
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   194
	 * dn_nblkptr is only one byte, so it's OK to read it in either
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   195
	 * byte order.  We can't read dn_bouslen.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   196
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   197
	ASSERT(dnp->dn_indblkshift <= SPA_MAXBLOCKSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   198
	ASSERT(dnp->dn_nblkptr <= DN_MAX_NBLKPTR);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   199
	for (i = 0; i < dnp->dn_nblkptr * sizeof (blkptr_t)/8; i++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   200
		buf64[i] = BSWAP_64(buf64[i]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   201
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   202
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   203
	 * OK to check dn_bonuslen for zero, because it won't matter if
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   204
	 * we have the wrong byte order.  This is necessary because the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   205
	 * dnode dnode is smaller than a regular dnode.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   206
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   207
	if (dnp->dn_bonuslen != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   208
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   209
		 * Note that the bonus length calculated here may be
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   210
		 * longer than the actual bonus buffer.  This is because
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   211
		 * we always put the bonus buffer after the last block
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   212
		 * pointer (instead of packing it against the end of the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   213
		 * dnode buffer).
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   214
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   215
		int off = (dnp->dn_nblkptr-1) * sizeof (blkptr_t);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   216
		size_t len = DN_MAX_BONUSLEN - off;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   217
		dmu_ot[dnp->dn_bonustype].ot_byteswap(dnp->dn_bonus + off, len);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   218
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   219
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   220
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   221
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   222
dnode_buf_byteswap(void *vbuf, size_t size)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   223
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   224
	dnode_phys_t *buf = vbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   225
	int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   226
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   227
	ASSERT3U(sizeof (dnode_phys_t), ==, (1<<DNODE_SHIFT));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   228
	ASSERT((size & (sizeof (dnode_phys_t)-1)) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   229
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   230
	size >>= DNODE_SHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   231
	for (i = 0; i < size; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   232
		dnode_byteswap(buf);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   233
		buf++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   234
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   235
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   236
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   237
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   238
free_range_compar(const void *node1, const void *node2)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   239
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   240
	const free_range_t *rp1 = node1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   241
	const free_range_t *rp2 = node2;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   242
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   243
	if (rp1->fr_blkid < rp2->fr_blkid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   244
		return (-1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   245
	else if (rp1->fr_blkid > rp2->fr_blkid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   246
		return (1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   247
	else return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   248
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   249
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   250
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   251
dnode_setdblksz(dnode_t *dn, int size)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   252
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   253
	ASSERT3U(P2PHASE(size, SPA_MINBLOCKSIZE), ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   254
	ASSERT3U(size, <=, SPA_MAXBLOCKSIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   255
	ASSERT3U(size, >=, SPA_MINBLOCKSIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   256
	ASSERT3U(size >> SPA_MINBLOCKSHIFT, <,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   257
	    1<<(sizeof (dn->dn_phys->dn_datablkszsec) * 8));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   258
	dn->dn_datablksz = size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   259
	dn->dn_datablkszsec = size >> SPA_MINBLOCKSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   260
	dn->dn_datablkshift = ISP2(size) ? highbit(size - 1) : 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   261
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   262
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   263
static dnode_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   264
dnode_create(objset_impl_t *os, dnode_phys_t *dnp, dmu_buf_impl_t *db,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   265
    uint64_t object)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   266
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   267
	dnode_t *dn = kmem_cache_alloc(dnode_cache, KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   268
	(void) dnode_cons(dn, NULL, 0); /* XXX */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   269
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   270
	dn->dn_objset = os;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   271
	dn->dn_object = object;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   272
	dn->dn_dbuf = db;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   273
	dn->dn_phys = dnp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   274
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   275
	if (dnp->dn_datablkszsec)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   276
		dnode_setdblksz(dn, dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   277
	dn->dn_indblkshift = dnp->dn_indblkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   278
	dn->dn_nlevels = dnp->dn_nlevels;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   279
	dn->dn_type = dnp->dn_type;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   280
	dn->dn_nblkptr = dnp->dn_nblkptr;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   281
	dn->dn_checksum = dnp->dn_checksum;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   282
	dn->dn_compress = dnp->dn_compress;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   283
	dn->dn_bonustype = dnp->dn_bonustype;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   284
	dn->dn_bonuslen = dnp->dn_bonuslen;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   285
	dn->dn_maxblkid = dnp->dn_maxblkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   286
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   287
	dmu_zfetch_init(&dn->dn_zfetch, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   288
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   289
	ASSERT(dn->dn_phys->dn_type < DMU_OT_NUMTYPES);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   290
	mutex_enter(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   291
	list_insert_head(&os->os_dnodes, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   292
	mutex_exit(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   293
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   294
	return (dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   295
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   296
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   297
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   298
dnode_destroy(dnode_t *dn)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   299
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   300
	objset_impl_t *os = dn->dn_objset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   301
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   302
	mutex_enter(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   303
	list_remove(&os->os_dnodes, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   304
	mutex_exit(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   305
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   306
	if (dn->dn_dirtyctx_firstset) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   307
		kmem_free(dn->dn_dirtyctx_firstset, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   308
		dn->dn_dirtyctx_firstset = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   309
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   310
	dmu_zfetch_rele(&dn->dn_zfetch);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   311
	kmem_cache_free(dnode_cache, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   312
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   313
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   314
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   315
dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   316
	dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   317
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   318
	int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   319
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   320
	if (blocksize == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   321
		blocksize = 1 << zfs_default_bs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   322
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   323
	blocksize = MIN(MAX(blocksize, SPA_MINBLOCKSIZE), SPA_MAXBLOCKSIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   324
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   325
	if (ibs == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   326
		ibs = zfs_default_ibs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   327
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   328
	ibs = MIN(MAX(ibs, DN_MIN_INDBLKSHIFT), DN_MAX_INDBLKSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   329
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   330
	dprintf("os=%p obj=%llu txg=%llu blocksize=%d ibs=%d\n", dn->dn_objset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   331
	    dn->dn_object, tx->tx_txg, blocksize, ibs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   332
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   333
	ASSERT(dn->dn_type == DMU_OT_NONE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   334
	ASSERT(bcmp(dn->dn_phys, &dnode_phys_zero, sizeof (dnode_phys_t)) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   335
	ASSERT(dn->dn_phys->dn_type == DMU_OT_NONE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   336
	ASSERT(ot != DMU_OT_NONE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   337
	ASSERT3U(ot, <, DMU_OT_NUMTYPES);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   338
	ASSERT((bonustype == DMU_OT_NONE && bonuslen == 0) ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   339
	    (bonustype != DMU_OT_NONE && bonuslen != 0));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   340
	ASSERT3U(bonustype, <, DMU_OT_NUMTYPES);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   341
	ASSERT3U(bonuslen, <=, DN_MAX_BONUSLEN);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   342
	ASSERT(dn->dn_type == DMU_OT_NONE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   343
	ASSERT3U(dn->dn_maxblkid, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   344
	ASSERT3U(dn->dn_allocated_txg, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   345
	ASSERT3U(dn->dn_assigned_txg, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   346
	ASSERT(refcount_is_zero(&dn->dn_tx_holds));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   347
	ASSERT3U(refcount_count(&dn->dn_holds), <=, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   348
	ASSERT3P(list_head(&dn->dn_dbufs), ==, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   349
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   350
	for (i = 0; i < TXG_SIZE; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   351
		ASSERT3U(dn->dn_next_nlevels[i], ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   352
		ASSERT3U(dn->dn_next_indblkshift[i], ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   353
		ASSERT3U(dn->dn_dirtyblksz[i], ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   354
		ASSERT3P(list_head(&dn->dn_dirty_dbufs[i]), ==, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   355
		ASSERT3U(avl_numnodes(&dn->dn_ranges[i]), ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   356
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   357
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   358
	dn->dn_type = ot;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   359
	dnode_setdblksz(dn, blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   360
	dn->dn_indblkshift = ibs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   361
	dn->dn_nlevels = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   362
	dn->dn_nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   363
	dn->dn_bonustype = bonustype;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   364
	dn->dn_bonuslen = bonuslen;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   365
	dn->dn_checksum = ZIO_CHECKSUM_INHERIT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   366
	dn->dn_compress = ZIO_COMPRESS_INHERIT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   367
	dn->dn_dirtyctx = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   368
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   369
	dn->dn_free_txg = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   370
	if (dn->dn_dirtyctx_firstset) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   371
		kmem_free(dn->dn_dirtyctx_firstset, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   372
		dn->dn_dirtyctx_firstset = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   373
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   374
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   375
	dn->dn_allocated_txg = tx->tx_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   376
	dnode_setdirty(dn, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   377
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   378
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   379
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   380
dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   381
    dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   382
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   383
	dmu_buf_impl_t *db = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   384
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   385
	ASSERT3U(blocksize, >=, SPA_MINBLOCKSIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   386
	ASSERT3U(blocksize, <=, SPA_MAXBLOCKSIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   387
	ASSERT3U(blocksize % SPA_MINBLOCKSIZE, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   388
	ASSERT3P(list_head(&dn->dn_dbufs), ==, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   389
	ASSERT(!(dn->dn_object & DMU_PRIVATE_OBJECT) || dmu_tx_private_ok(tx));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   390
	ASSERT(tx->tx_txg != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   391
	ASSERT((bonustype == DMU_OT_NONE && bonuslen == 0) ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   392
	    (bonustype != DMU_OT_NONE && bonuslen != 0));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   393
	ASSERT3U(bonustype, <, DMU_OT_NUMTYPES);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   394
	ASSERT3U(bonuslen, <=, DN_MAX_BONUSLEN);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   395
	ASSERT(dn->dn_dirtyblksz[0] == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   396
	ASSERT(dn->dn_dirtyblksz[1] == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   397
	ASSERT(dn->dn_dirtyblksz[2] == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   398
	ASSERT(dn->dn_dirtyblksz[3] == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   399
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   400
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   401
	 * XXX I should really have a generation number to tell if we
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   402
	 * need to do this...
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   403
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   404
	if (blocksize != dn->dn_datablksz ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   405
	    dn->dn_bonustype != bonustype || dn->dn_bonuslen != bonuslen) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   406
		/* free all old data */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   407
		dnode_free_range(dn, 0, -1ULL, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   408
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   409
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   410
	/* change blocksize */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   411
	rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   412
	dnode_setdblksz(dn, blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   413
	dnode_setdirty(dn, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   414
	/* don't need dd_dirty_mtx, dnode is already dirty */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   415
	ASSERT(dn->dn_dirtyblksz[tx->tx_txg&TXG_MASK] != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   416
	dn->dn_dirtyblksz[tx->tx_txg&TXG_MASK] = blocksize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   417
	rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   418
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   419
	/* change type */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   420
	dn->dn_type = ot;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   421
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   422
	if (dn->dn_bonuslen != bonuslen) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   423
		/* change bonus size */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   424
		if (bonuslen == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   425
			bonuslen = 1; /* XXX */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   426
		db = dbuf_hold_bonus(dn, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   427
		dbuf_read(db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   428
		mutex_enter(&db->db_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   429
		ASSERT3U(db->db.db_size, ==, dn->dn_bonuslen);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   430
		ASSERT(db->db.db_data != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   431
		db->db.db_size = bonuslen;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   432
		mutex_exit(&db->db_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   433
		dbuf_dirty(db, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   434
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   435
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   436
	/* change bonus size and type */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   437
	mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   438
	dn->dn_bonustype = bonustype;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   439
	dn->dn_bonuslen = bonuslen;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   440
	dn->dn_nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   441
	dn->dn_checksum = ZIO_CHECKSUM_INHERIT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   442
	dn->dn_compress = ZIO_COMPRESS_INHERIT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   443
	ASSERT3U(dn->dn_nblkptr, <=, DN_MAX_NBLKPTR);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   444
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   445
	dn->dn_allocated_txg = tx->tx_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   446
	mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   447
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   448
	if (db)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   449
		dbuf_remove_ref(db, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   450
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   451
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   452
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   453
dnode_special_close(dnode_t *dn)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   454
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   455
	dnode_destroy(dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   456
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   457
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   458
dnode_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   459
dnode_special_open(objset_impl_t *os, dnode_phys_t *dnp, uint64_t object)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   460
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   461
	dnode_t *dn = dnode_create(os, dnp, NULL, object);
873
adefbfa5f42d 6347448 non ZFS_DEBUG kernels shouldn't call empty verify functions
ek110237
parents: 789
diff changeset
   462
	DNODE_VERIFY(dn);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   463
	return (dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   464
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   465
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   466
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   467
dnode_buf_pageout(dmu_buf_t *db, void *arg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   468
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   469
	dnode_t **children_dnodes = arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   470
	int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   471
	int epb = db->db_size >> DNODE_SHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   472
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   473
	for (i = 0; i < epb; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   474
		dnode_t *dn = children_dnodes[i];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   475
		int n;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   476
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   477
		if (dn == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   478
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   479
#ifdef ZFS_DEBUG
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   480
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   481
		 * If there are holds on this dnode, then there should
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   482
		 * be holds on the dnode's containing dbuf as well; thus
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   483
		 * it wouldn't be eligable for eviction and this function
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   484
		 * would not have been called.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   485
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   486
		ASSERT(refcount_is_zero(&dn->dn_holds));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   487
		ASSERT(list_head(&dn->dn_dbufs) == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   488
		ASSERT(refcount_is_zero(&dn->dn_tx_holds));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   489
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   490
		for (n = 0; n < TXG_SIZE; n++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   491
			ASSERT(dn->dn_dirtyblksz[n] == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   492
#endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   493
		children_dnodes[i] = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   494
		dnode_destroy(dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   495
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   496
	kmem_free(children_dnodes, epb * sizeof (dnode_t *));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   497
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   498
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   499
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   500
 * Returns held dnode if the object number is valid, NULL if not.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   501
 * Note that this will succeed even for free dnodes.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   502
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   503
dnode_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   504
dnode_hold_impl(objset_impl_t *os, uint64_t object, int flag, void *ref)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   505
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   506
	int epb, idx;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   507
	int drop_struct_lock = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   508
	uint64_t blk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   509
	dnode_t *mdn, *dn;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   510
	dmu_buf_impl_t *db;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   511
	dnode_t **children_dnodes;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   512
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   513
	if (object == 0 || object >= DN_MAX_OBJECT)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   514
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   515
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   516
	mdn = os->os_meta_dnode;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   517
873
adefbfa5f42d 6347448 non ZFS_DEBUG kernels shouldn't call empty verify functions
ek110237
parents: 789
diff changeset
   518
	DNODE_VERIFY(mdn);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   519
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   520
	if (!RW_WRITE_HELD(&mdn->dn_struct_rwlock)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   521
		rw_enter(&mdn->dn_struct_rwlock, RW_READER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   522
		drop_struct_lock = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   523
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   524
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   525
	blk = dbuf_whichblock(mdn, object * sizeof (dnode_phys_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   526
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   527
	db = dbuf_hold(mdn, blk);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   528
	if (drop_struct_lock)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   529
		rw_exit(&mdn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   530
	dbuf_read(db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   531
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   532
	ASSERT3U(db->db.db_size, >=, 1<<DNODE_SHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   533
	epb = db->db.db_size >> DNODE_SHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   534
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   535
	idx = object & (epb-1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   536
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   537
	children_dnodes = dmu_buf_get_user(&db->db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   538
	if (children_dnodes == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   539
		dnode_t **winner;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   540
		children_dnodes = kmem_zalloc(epb * sizeof (dnode_t *),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   541
		    KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   542
		if (winner = dmu_buf_set_user(&db->db, children_dnodes, NULL,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   543
		    dnode_buf_pageout)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   544
			kmem_free(children_dnodes, epb * sizeof (dnode_t *));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   545
			children_dnodes = winner;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   546
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   547
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   548
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   549
	if ((dn = children_dnodes[idx]) == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   550
		dnode_t *winner;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   551
		dn = dnode_create(os, (dnode_phys_t *)db->db.db_data+idx,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   552
			db, object);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   553
		winner = atomic_cas_ptr(&children_dnodes[idx], NULL, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   554
		if (winner != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   555
			dnode_destroy(dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   556
			dn = winner;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   557
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   558
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   559
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   560
	mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   561
	if (dn->dn_free_txg ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   562
	    ((flag & DNODE_MUST_BE_ALLOCATED) && dn->dn_type == DMU_OT_NONE) ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   563
	    ((flag & DNODE_MUST_BE_FREE) && dn->dn_type != DMU_OT_NONE)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   564
		mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   565
		dbuf_rele(db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   566
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   567
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   568
	mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   569
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   570
	if (refcount_add(&dn->dn_holds, ref) == 1)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   571
		dbuf_add_ref(db, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   572
873
adefbfa5f42d 6347448 non ZFS_DEBUG kernels shouldn't call empty verify functions
ek110237
parents: 789
diff changeset
   573
	DNODE_VERIFY(dn);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   574
	ASSERT3P(dn->dn_dbuf, ==, db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   575
	ASSERT3U(dn->dn_object, ==, object);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   576
	dbuf_rele(db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   577
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   578
	return (dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   579
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   580
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   581
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   582
 * Return held dnode if the object is allocated, NULL if not.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   583
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   584
dnode_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   585
dnode_hold(objset_impl_t *os, uint64_t object, void *ref)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   586
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   587
	return (dnode_hold_impl(os, object, DNODE_MUST_BE_ALLOCATED, ref));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   588
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   589
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   590
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   591
dnode_add_ref(dnode_t *dn, void *ref)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   592
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   593
	ASSERT(refcount_count(&dn->dn_holds) > 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   594
	(void) refcount_add(&dn->dn_holds, ref);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   595
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   596
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   597
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   598
dnode_rele(dnode_t *dn, void *ref)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   599
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   600
	uint64_t refs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   601
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   602
	refs = refcount_remove(&dn->dn_holds, ref);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   603
	/* NOTE: the DNODE_DNODE does not have a dn_dbuf */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   604
	if (refs == 0 && dn->dn_dbuf)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   605
		dbuf_remove_ref(dn->dn_dbuf, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   606
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   607
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   608
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   609
dnode_setdirty(dnode_t *dn, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   610
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   611
	objset_impl_t *os = dn->dn_objset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   612
	uint64_t txg = tx->tx_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   613
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   614
	if (IS_DNODE_DNODE(dn->dn_object))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   615
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   616
873
adefbfa5f42d 6347448 non ZFS_DEBUG kernels shouldn't call empty verify functions
ek110237
parents: 789
diff changeset
   617
	DNODE_VERIFY(dn);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   618
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   619
#ifdef ZFS_DEBUG
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   620
	mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   621
	ASSERT(dn->dn_phys->dn_type || dn->dn_allocated_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   622
	/* ASSERT(dn->dn_free_txg == 0 || dn->dn_free_txg >= txg); */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   623
	mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   624
#endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   625
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   626
	mutex_enter(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   627
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   628
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   629
	 * If we are already marked dirty, we're done.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   630
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   631
	if (dn->dn_dirtyblksz[txg&TXG_MASK] > 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   632
		mutex_exit(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   633
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   634
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   635
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   636
	ASSERT(!refcount_is_zero(&dn->dn_holds) || list_head(&dn->dn_dbufs));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   637
	ASSERT(dn->dn_datablksz != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   638
	dn->dn_dirtyblksz[txg&TXG_MASK] = dn->dn_datablksz;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   639
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   640
	dprintf_ds(os->os_dsl_dataset, "obj=%llu txg=%llu\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   641
	    dn->dn_object, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   642
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   643
	if (dn->dn_free_txg > 0 && dn->dn_free_txg <= txg) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   644
		list_insert_tail(&os->os_free_dnodes[txg&TXG_MASK], dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   645
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   646
		list_insert_tail(&os->os_dirty_dnodes[txg&TXG_MASK], dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   647
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   648
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   649
	mutex_exit(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   650
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   651
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   652
	 * The dnode maintains a hold on its containing dbuf as
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   653
	 * long as there are holds on it.  Each instantiated child
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   654
	 * dbuf maintaines a hold on the dnode.  When the last child
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   655
	 * drops its hold, the dnode will drop its hold on the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   656
	 * containing dbuf. We add a "dirty hold" here so that the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   657
	 * dnode will hang around after we finish processing its
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   658
	 * children.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   659
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   660
	(void) refcount_add(&dn->dn_holds, (void *)(uintptr_t)tx->tx_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   661
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   662
	dbuf_dirty(dn->dn_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   663
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   664
	dsl_dataset_dirty(os->os_dsl_dataset, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   665
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   666
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   667
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   668
dnode_free(dnode_t *dn, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   669
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   670
	dprintf("dn=%p txg=%llu\n", dn, tx->tx_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   671
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   672
	/* we should be the only holder... hopefully */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   673
	/* ASSERT3U(refcount_count(&dn->dn_holds), ==, 1); */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   674
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   675
	mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   676
	if (dn->dn_type == DMU_OT_NONE || dn->dn_free_txg) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   677
		mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   678
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   679
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   680
	dn->dn_free_txg = tx->tx_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   681
	mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   682
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   683
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   684
	 * If the dnode is already dirty, it needs to be moved from
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   685
	 * the dirty list to the free list.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   686
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   687
	mutex_enter(&dn->dn_objset->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   688
	if (dn->dn_dirtyblksz[tx->tx_txg&TXG_MASK] > 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   689
		list_remove(
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   690
		    &dn->dn_objset->os_dirty_dnodes[tx->tx_txg&TXG_MASK], dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   691
		list_insert_tail(
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   692
		    &dn->dn_objset->os_free_dnodes[tx->tx_txg&TXG_MASK], dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   693
		mutex_exit(&dn->dn_objset->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   694
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   695
		mutex_exit(&dn->dn_objset->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   696
		dnode_setdirty(dn, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   697
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   698
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   699
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   700
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   701
 * Try to change the block size for the indicated dnode.  This can only
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   702
 * succeed if there are no blocks allocated or dirty beyond first block
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   703
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   704
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   705
dnode_set_blksz(dnode_t *dn, uint64_t size, int ibs, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   706
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   707
	dmu_buf_impl_t *db, *db_next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   708
	int have_db0 = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   709
	int err = ENOTSUP;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   710
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   711
	if (size == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   712
		size = SPA_MINBLOCKSIZE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   713
	if (size > SPA_MAXBLOCKSIZE)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   714
		size = SPA_MAXBLOCKSIZE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   715
	else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   716
		size = P2ROUNDUP(size, SPA_MINBLOCKSIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   717
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   718
	if (ibs == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   719
		ibs = dn->dn_indblkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   720
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   721
	if (size >> SPA_MINBLOCKSHIFT == dn->dn_datablkszsec &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   722
	    ibs == dn->dn_indblkshift)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   723
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   724
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   725
	rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   726
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   727
	/* Check for any allocated blocks beyond the first */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   728
	if (dn->dn_phys->dn_maxblkid != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   729
		goto end;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   730
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   731
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   732
	 * Any buffers allocated for blocks beyond the first
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   733
	 * must be evictable/evicted, because they're the wrong size.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   734
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   735
	mutex_enter(&dn->dn_dbufs_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   736
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   737
	 * Since we have the dn_dbufs_mtx, nothing can be
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   738
	 * removed from dn_dbufs.  Since we have dn_struct_rwlock/w,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   739
	 * nothing can be added to dn_dbufs.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   740
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   741
	for (db = list_head(&dn->dn_dbufs); db; db = db_next) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   742
		db_next = list_next(&dn->dn_dbufs, db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   743
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   744
		if (db->db_blkid == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   745
			have_db0 = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   746
		} else if (db->db_blkid != DB_BONUS_BLKID) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   747
			mutex_exit(&dn->dn_dbufs_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   748
			goto end;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   749
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   750
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   751
	mutex_exit(&dn->dn_dbufs_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   752
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   753
	/* Fast-track if there is no data in the file */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   754
	if (BP_IS_HOLE(&dn->dn_phys->dn_blkptr[0]) && !have_db0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   755
		dnode_setdblksz(dn, size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   756
		dn->dn_indblkshift = ibs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   757
		dnode_setdirty(dn, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   758
		/* don't need dd_dirty_mtx, dnode is already dirty */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   759
		dn->dn_dirtyblksz[tx->tx_txg&TXG_MASK] = size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   760
		dn->dn_next_indblkshift[tx->tx_txg&TXG_MASK] = ibs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   761
		rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   762
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   763
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   764
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   765
	/* obtain the old block */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   766
	db = dbuf_hold(dn, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   767
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   768
	/* Not allowed to decrease the size if there is data present */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   769
	if (size < db->db.db_size) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   770
		dbuf_rele(db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   771
		goto end;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   772
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   773
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   774
	dbuf_new_size(db, size, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   775
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   776
	dnode_setdblksz(dn, size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   777
	dn->dn_indblkshift = ibs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   778
	/* don't need dd_dirty_mtx, dnode is already dirty */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   779
	dn->dn_dirtyblksz[tx->tx_txg&TXG_MASK] = size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   780
	dn->dn_next_indblkshift[tx->tx_txg&TXG_MASK] = ibs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   781
	dbuf_rele(db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   782
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   783
	err = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   784
end:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   785
	rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   786
	return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   787
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   788
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   789
uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   790
dnode_max_nonzero_offset(dnode_t *dn)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   791
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   792
	if (dn->dn_phys->dn_maxblkid == 0 &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   793
	    BP_IS_HOLE(&dn->dn_phys->dn_blkptr[0]))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   794
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   795
	else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   796
		return ((dn->dn_phys->dn_maxblkid+1) * dn->dn_datablksz);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   797
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   798
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   799
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   800
dnode_new_blkid(dnode_t *dn, uint64_t blkid, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   801
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   802
	uint64_t txgoff = tx->tx_txg & TXG_MASK;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   803
	int drop_struct_lock = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   804
	int epbs, old_nlevels, new_nlevels;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   805
	uint64_t sz;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   806
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   807
	if (blkid == DB_BONUS_BLKID)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   808
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   809
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   810
	if (!RW_WRITE_HELD(&dn->dn_struct_rwlock)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   811
		rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   812
		drop_struct_lock = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   813
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   814
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   815
	if (blkid > dn->dn_maxblkid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   816
		dn->dn_maxblkid = blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   817
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   818
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   819
	 * Compute the number of levels necessary to support the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   820
	 * new blkid.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   821
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   822
	new_nlevels = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   823
	epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   824
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   825
	for (sz = dn->dn_nblkptr; sz <= blkid && sz >= dn->dn_nblkptr;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   826
	    sz <<= epbs)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   827
		new_nlevels++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   828
	old_nlevels = dn->dn_nlevels;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   829
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   830
	if (new_nlevels > dn->dn_next_nlevels[txgoff])
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   831
		dn->dn_next_nlevels[txgoff] = new_nlevels;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   832
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   833
	if (new_nlevels > old_nlevels) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   834
		dprintf("dn %p increasing nlevels from %u to %u\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   835
		    dn, dn->dn_nlevels, new_nlevels);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   836
		dn->dn_nlevels = new_nlevels;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   837
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   838
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   839
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   840
	 * Dirty the left indirects.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   841
	 * Note: the caller should have just dnode_use_space()'d one
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   842
	 * data block's worth, so we could subtract that out of
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   843
	 * dn_inflight_data to determine if there is any dirty data
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   844
	 * besides this block.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   845
	 * We don't strictly need to dirty them unless there's
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   846
	 * *something* in the object (eg. on disk or dirty)...
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   847
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   848
	if (new_nlevels > old_nlevels) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   849
		dmu_buf_impl_t *db = dbuf_hold_level(dn, old_nlevels, 0, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   850
		dprintf("dn %p dirtying left indirects\n", dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   851
		dbuf_dirty(db, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   852
		dbuf_remove_ref(db, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   853
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   854
#ifdef ZFS_DEBUG
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   855
	else if (old_nlevels > 1 && new_nlevels > old_nlevels) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   856
		dmu_buf_impl_t *db;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   857
		int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   858
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   859
		for (i = 0; i < dn->dn_nblkptr; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   860
			db = dbuf_hold_level(dn, old_nlevels-1, i, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   861
			ASSERT(!
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   862
			    list_link_active(&db->db_dirty_node[txgoff]));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   863
			dbuf_remove_ref(db, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   864
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   865
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   866
#endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   867
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   868
	dprintf("dn %p done\n", dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   869
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   870
out:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   871
	if (drop_struct_lock)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   872
		rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   873
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   874
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   875
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   876
dnode_clear_range(dnode_t *dn, uint64_t blkid, uint64_t nblks, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   877
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   878
	avl_tree_t *tree = &dn->dn_ranges[tx->tx_txg&TXG_MASK];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   879
	avl_index_t where;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   880
	free_range_t *rp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   881
	free_range_t rp_tofind;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   882
	uint64_t endblk = blkid + nblks;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   883
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   884
	ASSERT(MUTEX_HELD(&dn->dn_mtx));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   885
	ASSERT(nblks <= UINT64_MAX - blkid); /* no overflow */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   886
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   887
	dprintf_dnode(dn, "blkid=%llu nblks=%llu txg=%llu\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   888
	    blkid, nblks, tx->tx_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   889
	rp_tofind.fr_blkid = blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   890
	rp = avl_find(tree, &rp_tofind, &where);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   891
	if (rp == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   892
		rp = avl_nearest(tree, where, AVL_BEFORE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   893
	if (rp == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   894
		rp = avl_nearest(tree, where, AVL_AFTER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   895
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   896
	while (rp && (rp->fr_blkid <= blkid + nblks)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   897
		uint64_t fr_endblk = rp->fr_blkid + rp->fr_nblks;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   898
		free_range_t *nrp = AVL_NEXT(tree, rp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   899
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   900
		if (blkid <= rp->fr_blkid && endblk >= fr_endblk) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   901
			/* clear this entire range */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   902
			avl_remove(tree, rp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   903
			kmem_free(rp, sizeof (free_range_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   904
		} else if (blkid <= rp->fr_blkid &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   905
		    endblk > rp->fr_blkid && endblk < fr_endblk) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   906
			/* clear the beginning of this range */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   907
			rp->fr_blkid = endblk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   908
			rp->fr_nblks = fr_endblk - endblk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   909
		} else if (blkid > rp->fr_blkid && blkid < fr_endblk &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   910
		    endblk >= fr_endblk) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   911
			/* clear the end of this range */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   912
			rp->fr_nblks = blkid - rp->fr_blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   913
		} else if (blkid > rp->fr_blkid && endblk < fr_endblk) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   914
			/* clear a chunk out of this range */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   915
			free_range_t *new_rp =
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   916
			    kmem_alloc(sizeof (free_range_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   917
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   918
			new_rp->fr_blkid = endblk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   919
			new_rp->fr_nblks = fr_endblk - endblk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   920
			avl_insert_here(tree, new_rp, rp, AVL_AFTER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   921
			rp->fr_nblks = blkid - rp->fr_blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   922
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   923
		/* there may be no overlap */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   924
		rp = nrp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   925
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   926
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   927
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   928
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   929
dnode_free_range(dnode_t *dn, uint64_t off, uint64_t len, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   930
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   931
	dmu_buf_impl_t *db;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   932
	uint64_t start, objsize, blkid, nblks;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   933
	int blkshift, blksz, tail, head, epbs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   934
	int trunc = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   935
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   936
	rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   937
	blksz = dn->dn_datablksz;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   938
	blkshift = dn->dn_datablkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   939
	epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   940
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   941
	/* If the range is past the end of the file, this is a no-op */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   942
	objsize = blksz * (dn->dn_maxblkid+1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   943
	if (off >= objsize)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   944
		goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   945
	if (len == -1ULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   946
		len = UINT64_MAX - off;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   947
		trunc = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   948
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   949
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   950
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   951
	 * First, block align the region to free:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   952
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   953
	if (dn->dn_maxblkid == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   954
		if (off == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   955
			head = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   956
		} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   957
			head = blksz - off;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   958
			ASSERT3U(head, >, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   959
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   960
		start = off;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   961
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   962
		ASSERT(ISP2(blksz));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   963
		head = P2NPHASE(off, blksz);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   964
		start = P2PHASE(off, blksz);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   965
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   966
	/* zero out any partial block data at the start of the range */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   967
	if (head) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   968
		ASSERT3U(start + head, ==, blksz);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   969
		if (len < head)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   970
			head = len;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   971
		if (dbuf_hold_impl(dn, 0, dbuf_whichblock(dn, off), TRUE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   972
		    FTAG, &db) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   973
			caddr_t data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   974
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   975
			/* don't dirty if it isn't on disk and isn't dirty */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   976
			if (db->db_dirtied ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   977
			    (db->db_blkptr && !BP_IS_HOLE(db->db_blkptr))) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   978
				rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   979
				dbuf_will_dirty(db, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   980
				rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   981
				data = db->db.db_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   982
				bzero(data + start, head);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   983
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   984
			dbuf_remove_ref(db, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   985
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   986
		off += head;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   987
		len -= head;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   988
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   989
	/* If the range was less than one block, we are done */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   990
	if (len == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   991
		goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   992
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   993
	/* If the remaining range is past the end of the file, we are done */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   994
	if (off > dn->dn_maxblkid << blkshift)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   995
		goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   996
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   997
	if (off + len == UINT64_MAX)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   998
		tail = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   999
	else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1000
		tail = P2PHASE(len, blksz);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1001
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1002
	ASSERT3U(P2PHASE(off, blksz), ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1003
	/* zero out any partial block data at the end of the range */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1004
	if (tail) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1005
		if (len < tail)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1006
			tail = len;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1007
		if (dbuf_hold_impl(dn, 0, dbuf_whichblock(dn, off+len),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1008
		    TRUE, FTAG, &db) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1009
			/* don't dirty if it isn't on disk and isn't dirty */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1010
			if (db->db_dirtied ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1011
			    (db->db_blkptr && !BP_IS_HOLE(db->db_blkptr))) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1012
				rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1013
				dbuf_will_dirty(db, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1014
				rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1015
				bzero(db->db.db_data, tail);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1016
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1017
			dbuf_remove_ref(db, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1018
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1019
		len -= tail;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1020
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1021
	/* If the range did not include a full block, we are done */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1022
	if (len == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1023
		goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1024
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1025
	/* dirty the left indirects */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1026
	if (dn->dn_nlevels > 1 && off != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1027
		db = dbuf_hold_level(dn, 1,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1028
		    (off - head) >> (blkshift + epbs), FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1029
		dbuf_will_dirty(db, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1030
		dbuf_remove_ref(db, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1031
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1032
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1033
	/* dirty the right indirects */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1034
	if (dn->dn_nlevels > 1 && !trunc) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1035
		db = dbuf_hold_level(dn, 1,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1036
		    (off + len + tail - 1) >> (blkshift + epbs), FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1037
		dbuf_will_dirty(db, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1038
		dbuf_remove_ref(db, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1039
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1040
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1041
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1042
	 * Finally, add this range to the dnode range list, we
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1043
	 * will finish up this free operation in the syncing phase.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1044
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1045
	ASSERT(IS_P2ALIGNED(off, 1<<blkshift));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1046
	ASSERT(off + len == UINT64_MAX || IS_P2ALIGNED(len, 1<<blkshift));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1047
	blkid = off >> blkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1048
	nblks = len >> blkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1049
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1050
	if (trunc)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1051
		dn->dn_maxblkid = (blkid ? blkid - 1 : 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1052
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1053
	mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1054
	dnode_clear_range(dn, blkid, nblks, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1055
	{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1056
		free_range_t *rp, *found;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1057
		avl_index_t where;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1058
		avl_tree_t *tree = &dn->dn_ranges[tx->tx_txg&TXG_MASK];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1059
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1060
		/* Add new range to dn_ranges */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1061
		rp = kmem_alloc(sizeof (free_range_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1062
		rp->fr_blkid = blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1063
		rp->fr_nblks = nblks;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1064
		found = avl_find(tree, rp, &where);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1065
		ASSERT(found == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1066
		avl_insert(tree, rp, where);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1067
		dprintf_dnode(dn, "blkid=%llu nblks=%llu txg=%llu\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1068
		    blkid, nblks, tx->tx_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1069
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1070
	mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1071
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1072
	dbuf_free_range(dn, blkid, nblks, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1073
	dnode_setdirty(dn, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1074
out:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1075
	rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1076
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1077
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1078
/* return TRUE if this blkid was freed in a recent txg, or FALSE if it wasn't */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1079
uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1080
dnode_block_freed(dnode_t *dn, uint64_t blkid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1081
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1082
	free_range_t range_tofind;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1083
	void *dp = spa_get_dsl(dn->dn_objset->os_spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1084
	int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1085
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1086
	if (blkid == DB_BONUS_BLKID)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1087
		return (FALSE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1088
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1089
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1090
	 * If we're in the process of opening the pool, dp will not be
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1091
	 * set yet, but there shouldn't be anything dirty.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1092
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1093
	if (dp == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1094
		return (FALSE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1095
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1096
	if (dn->dn_free_txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1097
		return (TRUE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1098
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1099
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1100
	 * If dn_datablkshift is not set, then there's only a single
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1101
	 * block, in which case there will never be a free range so it
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1102
	 * won't matter.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1103
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1104
	range_tofind.fr_blkid = blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1105
	mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1106
	for (i = 0; i < TXG_SIZE; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1107
		free_range_t *range_found;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1108
		avl_index_t idx;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1109
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1110
		range_found = avl_find(&dn->dn_ranges[i], &range_tofind, &idx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1111
		if (range_found) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1112
			ASSERT(range_found->fr_nblks > 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1113
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1114
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1115
		range_found = avl_nearest(&dn->dn_ranges[i], idx, AVL_BEFORE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1116
		if (range_found &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1117
		    range_found->fr_blkid + range_found->fr_nblks > blkid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1118
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1119
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1120
	mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1121
	return (i < TXG_SIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1122
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1123
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1124
/* call from syncing context when we actually write/free space for this dnode */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1125
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1126
dnode_diduse_space(dnode_t *dn, int64_t space)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1127
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1128
	uint64_t sectors;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1129
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1130
	dprintf_dnode(dn, "dn=%p dnp=%p secphys=%llu space=%lld\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1131
	    dn, dn->dn_phys,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1132
	    (u_longlong_t)dn->dn_phys->dn_secphys,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1133
	    (longlong_t)space);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1134
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1135
	ASSERT(P2PHASE(space, 1<<DEV_BSHIFT) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1136
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1137
	mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1138
	if (space > 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1139
		sectors = space >> DEV_BSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1140
		ASSERT3U(dn->dn_phys->dn_secphys + sectors, >=,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1141
		    dn->dn_phys->dn_secphys);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1142
		dn->dn_phys->dn_secphys += sectors;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1143
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1144
		sectors = -space >> DEV_BSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1145
		ASSERT3U(dn->dn_phys->dn_secphys, >=, sectors);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1146
		dn->dn_phys->dn_secphys -= sectors;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1147
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1148
	mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1149
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1150
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1151
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1152
 * Call when we think we're going to write/free space in open context.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1153
 * Be conservative (ie. OK to write less than this or free more than
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1154
 * this, but don't write more or free less).
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1155
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1156
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1157
dnode_willuse_space(dnode_t *dn, int64_t space, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1158
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1159
	objset_impl_t *os = dn->dn_objset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1160
	dsl_dataset_t *ds = os->os_dsl_dataset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1161
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1162
	if (space > 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1163
		space = spa_get_asize(os->os_spa, space);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1164
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1165
	if (ds)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1166
		dsl_dir_willuse_space(ds->ds_dir, space, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1167
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1168
	dmu_tx_willuse_space(tx, space);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1169
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1170
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1171
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1172
dnode_next_offset_level(dnode_t *dn, boolean_t hole, uint64_t *offset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1173
	int lvl, uint64_t blkfill)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1174
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1175
	dmu_buf_impl_t *db = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1176
	void *data = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1177
	uint64_t epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1178
	uint64_t epb = 1ULL << epbs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1179
	uint64_t minfill, maxfill;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1180
	int i, error, span;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1181
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1182
	dprintf("probing object %llu offset %llx level %d of %u\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1183
	    dn->dn_object, *offset, lvl, dn->dn_phys->dn_nlevels);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1184
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1185
	if (lvl == dn->dn_phys->dn_nlevels) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1186
		error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1187
		epb = dn->dn_phys->dn_nblkptr;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1188
		data = dn->dn_phys->dn_blkptr;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1189
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1190
		uint64_t blkid = dbuf_whichblock(dn, *offset) >> (epbs * lvl);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1191
		error = dbuf_hold_impl(dn, lvl, blkid, TRUE, FTAG, &db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1192
		if (error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1193
			if (error == ENOENT)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1194
				return (hole ? 0 : ESRCH);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1195
			return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1196
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1197
		dbuf_read_havestruct(db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1198
		data = db->db.db_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1199
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1200
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1201
	if (lvl == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1202
		dnode_phys_t *dnp = data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1203
		span = DNODE_SHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1204
		ASSERT(dn->dn_type == DMU_OT_DNODE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1205
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1206
		for (i = (*offset >> span) & (blkfill - 1); i < blkfill; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1207
			if (!dnp[i].dn_type == hole)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1208
				break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1209
			*offset += 1ULL << span;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1210
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1211
		if (i == blkfill)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1212
			error = ESRCH;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1213
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1214
		blkptr_t *bp = data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1215
		span = (lvl - 1) * epbs + dn->dn_datablkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1216
		minfill = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1217
		maxfill = blkfill << ((lvl - 1) * epbs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1218
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1219
		if (hole)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1220
			maxfill--;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1221
		else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1222
			minfill++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1223
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1224
		for (i = (*offset >> span) & ((1ULL << epbs) - 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1225
		    i < epb; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1226
			if (bp[i].blk_fill >= minfill &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1227
			    bp[i].blk_fill <= maxfill)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1228
				break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1229
			*offset += 1ULL << span;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1230
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1231
		if (i >= epb)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1232
			error = ESRCH;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1233
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1234
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1235
	if (db)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1236
		dbuf_remove_ref(db, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1237
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1238
	return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1239
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1240
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1241
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1242
 * Find the next hole, data, or sparse region at or after *offset.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1243
 * The value 'blkfill' tells us how many items we expect to find
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1244
 * in an L0 data block; this value is 1 for normal objects,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1245
 * DNODES_PER_BLOCK for the meta dnode, and some fraction of
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1246
 * DNODES_PER_BLOCK when searching for sparse regions thereof.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1247
 * Examples:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1248
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1249
 * dnode_next_offset(dn, hole, offset, 1, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1250
 *	Finds the next hole/data in a file.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1251
 *	Used in dmu_offset_next().
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1252
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1253
 * dnode_next_offset(mdn, hole, offset, 0, DNODES_PER_BLOCK);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1254
 *	Finds the next free/allocated dnode an objset's meta-dnode.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1255
 *	Used in dmu_object_next().
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1256
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1257
 * dnode_next_offset(mdn, TRUE, offset, 2, DNODES_PER_BLOCK >> 2);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1258
 *	Finds the next L2 meta-dnode bp that's at most 1/4 full.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1259
 *	Used in dmu_object_alloc().
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1260
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1261
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1262
dnode_next_offset(dnode_t *dn, boolean_t hole, uint64_t *offset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1263
    int minlvl, uint64_t blkfill)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1264
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1265
	int lvl, maxlvl;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1266
	int error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1267
	uint64_t initial_offset = *offset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1268
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1269
	rw_enter(&dn->dn_struct_rwlock, RW_READER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1270
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1271
	if (dn->dn_phys->dn_nlevels == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1272
		rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1273
		return (ESRCH);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1274
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1275
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1276
	if (dn->dn_datablkshift == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1277
		if (*offset < dn->dn_datablksz) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1278
			if (hole)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1279
				*offset = dn->dn_datablksz;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1280
		} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1281
			error = ESRCH;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1282
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1283
		rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1284
		return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1285
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1286
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1287
	maxlvl = dn->dn_phys->dn_nlevels;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1288
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1289
	for (lvl = minlvl; lvl <= maxlvl; lvl++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1290
		error = dnode_next_offset_level(dn, hole, offset, lvl, blkfill);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1291
		if (error == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1292
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1293
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1294
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1295
	while (--lvl >= minlvl && error == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1296
		error = dnode_next_offset_level(dn, hole, offset, lvl, blkfill);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1297
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1298
	rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1299
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1300
	if (initial_offset > *offset)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1301
		return (ESRCH);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1302
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1303
	return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1304
}