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