annotate usr/src/uts/common/fs/zfs/dnode.c @ 2082:76b439ec3ac1

PSARC 2006/223 ZFS Hot Spares PSARC 2006/303 ZFS Clone Promotion 6276916 support for "clone swap" 6288488 du reports misleading size on RAID-Z 6393490 libzfs should be a real library 6397148 fbufs debug code should be removed from buf_hash_insert() 6405966 Hot Spare support in ZFS 6409302 passing a non-root vdev via zpool_create() panics system 6415739 assertion failed: !(zio->io_flags & 0x00040) 6416759 ::dbufs does not find bonus buffers anymore 6417978 double parity RAID-Z a.k.a. RAID6 6424554 full block re-writes need not read data in 6425111 detaching an offline device can result in import confusion
author eschrock
date Tue, 30 May 2006 15:47:16 -0700
parents 2960cf15fee6
children 45c1310316ff
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
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_datablkszsec = BSWAP_16(dnp->dn_datablkszsec);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
181 dnp->dn_bonuslen = BSWAP_16(dnp->dn_bonuslen);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
182 dnp->dn_maxblkid = BSWAP_64(dnp->dn_maxblkid);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
183 dnp->dn_used = BSWAP_64(dnp->dn_used);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
184
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
185 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
186 * dn_nblkptr is only one byte, so it's OK to read it in either
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
187 * byte order. We can't read dn_bouslen.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
188 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
189 ASSERT(dnp->dn_indblkshift <= SPA_MAXBLOCKSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
190 ASSERT(dnp->dn_nblkptr <= DN_MAX_NBLKPTR);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
191 for (i = 0; i < dnp->dn_nblkptr * sizeof (blkptr_t)/8; i++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
192 buf64[i] = BSWAP_64(buf64[i]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
193
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
194 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
195 * OK to check dn_bonuslen for zero, because it won't matter if
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
196 * we have the wrong byte order. This is necessary because the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
197 * dnode dnode is smaller than a regular dnode.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
198 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
199 if (dnp->dn_bonuslen != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
200 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
201 * Note that the bonus length calculated here may be
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
202 * longer than the actual bonus buffer. This is because
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
203 * we always put the bonus buffer after the last block
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
204 * pointer (instead of packing it against the end of the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
205 * dnode buffer).
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
206 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
207 int off = (dnp->dn_nblkptr-1) * sizeof (blkptr_t);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
208 size_t len = DN_MAX_BONUSLEN - off;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
209 dmu_ot[dnp->dn_bonustype].ot_byteswap(dnp->dn_bonus + off, len);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
210 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
211 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
212
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
213 void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
214 dnode_buf_byteswap(void *vbuf, size_t size)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
215 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
216 dnode_phys_t *buf = vbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
217 int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
218
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
219 ASSERT3U(sizeof (dnode_phys_t), ==, (1<<DNODE_SHIFT));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
220 ASSERT((size & (sizeof (dnode_phys_t)-1)) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
221
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
222 size >>= DNODE_SHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
223 for (i = 0; i < size; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
224 dnode_byteswap(buf);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
225 buf++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
226 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
227 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
228
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
229 static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
230 free_range_compar(const void *node1, const void *node2)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
231 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
232 const free_range_t *rp1 = node1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
233 const free_range_t *rp2 = node2;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
234
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
235 if (rp1->fr_blkid < rp2->fr_blkid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
236 return (-1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
237 else if (rp1->fr_blkid > rp2->fr_blkid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
238 return (1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
239 else return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
240 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
241
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
242 static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
243 dnode_setdblksz(dnode_t *dn, int size)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
244 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
245 ASSERT3U(P2PHASE(size, SPA_MINBLOCKSIZE), ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
246 ASSERT3U(size, <=, SPA_MAXBLOCKSIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
247 ASSERT3U(size, >=, SPA_MINBLOCKSIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
248 ASSERT3U(size >> SPA_MINBLOCKSHIFT, <,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
249 1<<(sizeof (dn->dn_phys->dn_datablkszsec) * 8));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
250 dn->dn_datablksz = size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
251 dn->dn_datablkszsec = size >> SPA_MINBLOCKSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
252 dn->dn_datablkshift = ISP2(size) ? highbit(size - 1) : 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
253 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
254
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
255 static dnode_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
256 dnode_create(objset_impl_t *os, dnode_phys_t *dnp, dmu_buf_impl_t *db,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
257 uint64_t object)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
258 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
259 dnode_t *dn = kmem_cache_alloc(dnode_cache, KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
260 (void) dnode_cons(dn, NULL, 0); /* XXX */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
261
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
262 dn->dn_objset = os;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
263 dn->dn_object = object;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
264 dn->dn_dbuf = db;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
265 dn->dn_phys = dnp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
266
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
267 if (dnp->dn_datablkszsec)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
268 dnode_setdblksz(dn, dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
269 dn->dn_indblkshift = dnp->dn_indblkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
270 dn->dn_nlevels = dnp->dn_nlevels;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
271 dn->dn_type = dnp->dn_type;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
272 dn->dn_nblkptr = dnp->dn_nblkptr;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
273 dn->dn_checksum = dnp->dn_checksum;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
274 dn->dn_compress = dnp->dn_compress;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
275 dn->dn_bonustype = dnp->dn_bonustype;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
276 dn->dn_bonuslen = dnp->dn_bonuslen;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
277 dn->dn_maxblkid = dnp->dn_maxblkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
278
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
279 dmu_zfetch_init(&dn->dn_zfetch, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
280
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
281 ASSERT(dn->dn_phys->dn_type < DMU_OT_NUMTYPES);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
282 mutex_enter(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
283 list_insert_head(&os->os_dnodes, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
284 mutex_exit(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
285
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
286 return (dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
287 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
288
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
289 static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
290 dnode_destroy(dnode_t *dn)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
291 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
292 objset_impl_t *os = dn->dn_objset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
293
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
294 mutex_enter(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
295 list_remove(&os->os_dnodes, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
296 mutex_exit(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
297
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
298 if (dn->dn_dirtyctx_firstset) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
299 kmem_free(dn->dn_dirtyctx_firstset, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
300 dn->dn_dirtyctx_firstset = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
301 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
302 dmu_zfetch_rele(&dn->dn_zfetch);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
303 if (dn->dn_bonus) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
304 mutex_enter(&dn->dn_bonus->db_mtx);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
305 dbuf_evict(dn->dn_bonus);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
306 dn->dn_bonus = NULL;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
307 }
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
308 kmem_cache_free(dnode_cache, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
309 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
310
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
311 void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
312 dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs,
1599
b2940ec637b4 6397222 corrupt microzap object
ahrens
parents: 1596
diff changeset
313 dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
314 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
315 int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
316
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
317 if (blocksize == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
318 blocksize = 1 << zfs_default_bs;
1402
bfaffef2800c 6382360 dnode_setblksz assertion failed
ahrens
parents: 873
diff changeset
319 else if (blocksize > SPA_MAXBLOCKSIZE)
bfaffef2800c 6382360 dnode_setblksz assertion failed
ahrens
parents: 873
diff changeset
320 blocksize = SPA_MAXBLOCKSIZE;
bfaffef2800c 6382360 dnode_setblksz assertion failed
ahrens
parents: 873
diff changeset
321 else
bfaffef2800c 6382360 dnode_setblksz assertion failed
ahrens
parents: 873
diff changeset
322 blocksize = P2ROUNDUP(blocksize, SPA_MINBLOCKSIZE);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
323
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
324 if (ibs == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
325 ibs = zfs_default_ibs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
326
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
327 ibs = MIN(MAX(ibs, DN_MIN_INDBLKSHIFT), DN_MAX_INDBLKSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
328
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
329 dprintf("os=%p obj=%llu txg=%llu blocksize=%d ibs=%d\n", dn->dn_objset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
330 dn->dn_object, tx->tx_txg, blocksize, ibs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
331
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
332 ASSERT(dn->dn_type == DMU_OT_NONE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
333 ASSERT(bcmp(dn->dn_phys, &dnode_phys_zero, sizeof (dnode_phys_t)) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
334 ASSERT(dn->dn_phys->dn_type == DMU_OT_NONE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
335 ASSERT(ot != DMU_OT_NONE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
336 ASSERT3U(ot, <, DMU_OT_NUMTYPES);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
337 ASSERT((bonustype == DMU_OT_NONE && bonuslen == 0) ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
338 (bonustype != DMU_OT_NONE && bonuslen != 0));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
339 ASSERT3U(bonustype, <, DMU_OT_NUMTYPES);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
340 ASSERT3U(bonuslen, <=, DN_MAX_BONUSLEN);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
341 ASSERT(dn->dn_type == DMU_OT_NONE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
342 ASSERT3U(dn->dn_maxblkid, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
343 ASSERT3U(dn->dn_allocated_txg, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
344 ASSERT3U(dn->dn_assigned_txg, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
345 ASSERT(refcount_is_zero(&dn->dn_tx_holds));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
346 ASSERT3U(refcount_count(&dn->dn_holds), <=, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
347 ASSERT3P(list_head(&dn->dn_dbufs), ==, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
348
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
349 for (i = 0; i < TXG_SIZE; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
350 ASSERT3U(dn->dn_next_nlevels[i], ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
351 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
352 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
353 ASSERT(!list_link_active(&dn->dn_dirty_link[i]));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
354 ASSERT3P(list_head(&dn->dn_dirty_dbufs[i]), ==, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
355 ASSERT3U(avl_numnodes(&dn->dn_ranges[i]), ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
356 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
357
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
358 dn->dn_type = ot;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
359 dnode_setdblksz(dn, blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
360 dn->dn_indblkshift = ibs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
361 dn->dn_nlevels = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
362 dn->dn_nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
363 dn->dn_bonustype = bonustype;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
364 dn->dn_bonuslen = bonuslen;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
365 dn->dn_checksum = ZIO_CHECKSUM_INHERIT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
366 dn->dn_compress = ZIO_COMPRESS_INHERIT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
367 dn->dn_dirtyctx = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
368
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
369 dn->dn_free_txg = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
370 if (dn->dn_dirtyctx_firstset) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
371 kmem_free(dn->dn_dirtyctx_firstset, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
372 dn->dn_dirtyctx_firstset = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
373 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
374
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
375 dn->dn_allocated_txg = tx->tx_txg;
1599
b2940ec637b4 6397222 corrupt microzap object
ahrens
parents: 1596
diff changeset
376
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
377 dnode_setdirty(dn, tx);
1599
b2940ec637b4 6397222 corrupt microzap object
ahrens
parents: 1596
diff changeset
378 dn->dn_next_indblkshift[tx->tx_txg & TXG_MASK] = ibs;
b2940ec637b4 6397222 corrupt microzap object
ahrens
parents: 1596
diff changeset
379 dn->dn_next_blksz[tx->tx_txg & TXG_MASK] = dn->dn_datablksz;
789
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 void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
383 dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
384 dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
385 {
1596
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
386 int i;
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
387
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
388 ASSERT3U(blocksize, >=, SPA_MINBLOCKSIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
389 ASSERT3U(blocksize, <=, SPA_MAXBLOCKSIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
390 ASSERT3U(blocksize % SPA_MINBLOCKSIZE, ==, 0);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
391 ASSERT(dn->dn_object != DMU_META_DNODE_OBJECT || dmu_tx_private_ok(tx));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
392 ASSERT(tx->tx_txg != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
393 ASSERT((bonustype == DMU_OT_NONE && bonuslen == 0) ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
394 (bonustype != DMU_OT_NONE && bonuslen != 0));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
395 ASSERT3U(bonustype, <, DMU_OT_NUMTYPES);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
396 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
397
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
398 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
399 ASSERT(!list_link_active(&dn->dn_dirty_link[i]));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
400
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
401 /* clean up any unreferenced dbufs */
1646
b4e43ae19fff 6393443 Remove remaining txg_wait_synced() from zfs unmount path.
perrin
parents: 1599
diff changeset
402 (void) dnode_evict_dbufs(dn, 0);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
403 ASSERT3P(list_head(&dn->dn_dbufs), ==, NULL);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
404
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
405 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
406 * XXX I should really have a generation number to tell if we
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
407 * need to do this...
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
408 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
409 if (blocksize != dn->dn_datablksz ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
410 dn->dn_bonustype != bonustype || dn->dn_bonuslen != bonuslen) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
411 /* free all old data */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
412 dnode_free_range(dn, 0, -1ULL, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
413 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
414
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
415 /* change blocksize */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
416 rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
417 dnode_setdblksz(dn, blocksize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
418 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
419 dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = blocksize;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
420 rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
421
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
422 /* change type */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
423 dn->dn_type = ot;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
424
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
425 if (dn->dn_bonuslen != bonuslen) {
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
426 dmu_buf_impl_t *db = NULL;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
427
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
428 /* change bonus size */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
429 if (bonuslen == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
430 bonuslen = 1; /* XXX */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
431 rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
432 if (dn->dn_bonus == NULL)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
433 dn->dn_bonus = dbuf_create_bonus(dn);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
434 db = dn->dn_bonus;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
435 rw_exit(&dn->dn_struct_rwlock);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
436 if (refcount_add(&db->db_holds, FTAG) == 1)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
437 dnode_add_ref(dn, db);
1990
2960cf15fee6 6416794 zfs panics in dnode_reallocate during incremental zfs restore
maybee
parents: 1793
diff changeset
438 VERIFY(0 == dbuf_read(db, NULL, DB_RF_MUST_SUCCEED));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
439 mutex_enter(&db->db_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
440 ASSERT3U(db->db.db_size, ==, dn->dn_bonuslen);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
441 ASSERT(db->db.db_data != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
442 db->db.db_size = bonuslen;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
443 mutex_exit(&db->db_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
444 dbuf_dirty(db, tx);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
445 dbuf_rele(db, FTAG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
446 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
447
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
448 /* change bonus size and type */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
449 mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
450 dn->dn_bonustype = bonustype;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
451 dn->dn_bonuslen = bonuslen;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
452 dn->dn_nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
453 dn->dn_checksum = ZIO_CHECKSUM_INHERIT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
454 dn->dn_compress = ZIO_COMPRESS_INHERIT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
455 ASSERT3U(dn->dn_nblkptr, <=, DN_MAX_NBLKPTR);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
456
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
457 dn->dn_allocated_txg = tx->tx_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
458 mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
459 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
460
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
461 void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
462 dnode_special_close(dnode_t *dn)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
463 {
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
464 /*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
465 * Wait for final references to the dnode to clear. This can
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
466 * only happen if the arc is asyncronously evicting state that
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
467 * has a hold on this dnode while we are trying to evict this
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
468 * dnode.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
469 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
470 while (refcount_count(&dn->dn_holds) > 0)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
471 delay(1);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
472 dnode_destroy(dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
473 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
474
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
475 dnode_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
476 dnode_special_open(objset_impl_t *os, dnode_phys_t *dnp, uint64_t object)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
477 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
478 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
479 DNODE_VERIFY(dn);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
480 return (dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
481 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
482
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
483 static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
484 dnode_buf_pageout(dmu_buf_t *db, void *arg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
485 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
486 dnode_t **children_dnodes = arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
487 int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
488 int epb = db->db_size >> DNODE_SHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
489
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
490 for (i = 0; i < epb; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
491 dnode_t *dn = children_dnodes[i];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
492 int n;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
493
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
494 if (dn == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
495 continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
496 #ifdef ZFS_DEBUG
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
497 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
498 * If there are holds on this dnode, then there should
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
499 * be holds on the dnode's containing dbuf as well; thus
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
500 * it wouldn't be eligable for eviction and this function
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
501 * would not have been called.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
502 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
503 ASSERT(refcount_is_zero(&dn->dn_holds));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
504 ASSERT(list_head(&dn->dn_dbufs) == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
505 ASSERT(refcount_is_zero(&dn->dn_tx_holds));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
506
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
507 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
508 ASSERT(!list_link_active(&dn->dn_dirty_link[n]));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
509 #endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
510 children_dnodes[i] = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
511 dnode_destroy(dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
512 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
513 kmem_free(children_dnodes, epb * sizeof (dnode_t *));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
514 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
515
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
516 /*
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
517 * errors:
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
518 * EINVAL - invalid object number.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
519 * EIO - i/o error.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
520 * succeeds even for free dnodes.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
521 */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
522 int
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
523 dnode_hold_impl(objset_impl_t *os, uint64_t object, int flag,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
524 void *tag, dnode_t **dnp)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
525 {
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
526 int epb, idx, err;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
527 int drop_struct_lock = FALSE;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
528 int type;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
529 uint64_t blk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
530 dnode_t *mdn, *dn;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
531 dmu_buf_impl_t *db;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
532 dnode_t **children_dnodes;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
533
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
534 if (object == 0 || object >= DN_MAX_OBJECT)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
535 return (EINVAL);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
536
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
537 mdn = os->os_meta_dnode;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
538
873
adefbfa5f42d 6347448 non ZFS_DEBUG kernels shouldn't call empty verify functions
ek110237
parents: 789
diff changeset
539 DNODE_VERIFY(mdn);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
540
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
541 if (!RW_WRITE_HELD(&mdn->dn_struct_rwlock)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
542 rw_enter(&mdn->dn_struct_rwlock, RW_READER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
543 drop_struct_lock = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
544 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
545
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
546 blk = dbuf_whichblock(mdn, object * sizeof (dnode_phys_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
547
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
548 db = dbuf_hold(mdn, blk, FTAG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
549 if (drop_struct_lock)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
550 rw_exit(&mdn->dn_struct_rwlock);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
551 if (db == NULL)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
552 return (EIO);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
553 err = dbuf_read(db, NULL, DB_RF_CANFAIL);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
554 if (err) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
555 dbuf_rele(db, FTAG);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
556 return (err);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
557 }
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
558
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
559 ASSERT3U(db->db.db_size, >=, 1<<DNODE_SHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
560 epb = db->db.db_size >> DNODE_SHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
561
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
562 idx = object & (epb-1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
563
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
564 children_dnodes = dmu_buf_get_user(&db->db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
565 if (children_dnodes == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
566 dnode_t **winner;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
567 children_dnodes = kmem_zalloc(epb * sizeof (dnode_t *),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
568 KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
569 if (winner = dmu_buf_set_user(&db->db, children_dnodes, NULL,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
570 dnode_buf_pageout)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
571 kmem_free(children_dnodes, epb * sizeof (dnode_t *));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
572 children_dnodes = winner;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
573 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
574 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
575
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
576 if ((dn = children_dnodes[idx]) == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
577 dnode_t *winner;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
578 dn = dnode_create(os, (dnode_phys_t *)db->db.db_data+idx,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
579 db, object);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
580 winner = atomic_cas_ptr(&children_dnodes[idx], NULL, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
581 if (winner != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
582 dnode_destroy(dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
583 dn = winner;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
584 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
585 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
586
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
587 mutex_enter(&dn->dn_mtx);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
588 type = dn->dn_type;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
589 if (dn->dn_free_txg ||
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
590 ((flag & DNODE_MUST_BE_ALLOCATED) && type == DMU_OT_NONE) ||
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
591 ((flag & DNODE_MUST_BE_FREE) && type != DMU_OT_NONE)) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
592 mutex_exit(&dn->dn_mtx);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
593 dbuf_rele(db, FTAG);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
594 return (type == DMU_OT_NONE ? ENOENT : EEXIST);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
595 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
596 mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
597
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
598 if (refcount_add(&dn->dn_holds, tag) == 1)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
599 dbuf_add_ref(db, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
600
873
adefbfa5f42d 6347448 non ZFS_DEBUG kernels shouldn't call empty verify functions
ek110237
parents: 789
diff changeset
601 DNODE_VERIFY(dn);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
602 ASSERT3P(dn->dn_dbuf, ==, db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
603 ASSERT3U(dn->dn_object, ==, object);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
604 dbuf_rele(db, FTAG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
605
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
606 *dnp = dn;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
607 return (0);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
608 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
609
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
610 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
611 * Return held dnode if the object is allocated, NULL if not.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
612 */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
613 int
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
614 dnode_hold(objset_impl_t *os, uint64_t object, void *tag, dnode_t **dnp)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
615 {
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
616 return (dnode_hold_impl(os, object, DNODE_MUST_BE_ALLOCATED, tag, dnp));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
617 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
618
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
619 void
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
620 dnode_add_ref(dnode_t *dn, void *tag)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
621 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
622 ASSERT(refcount_count(&dn->dn_holds) > 0);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
623 (void) refcount_add(&dn->dn_holds, tag);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
624 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
625
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
626 void
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
627 dnode_rele(dnode_t *dn, void *tag)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
628 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
629 uint64_t refs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
630
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
631 refs = refcount_remove(&dn->dn_holds, tag);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
632 /* NOTE: the DNODE_DNODE does not have a dn_dbuf */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
633 if (refs == 0 && dn->dn_dbuf)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
634 dbuf_rele(dn->dn_dbuf, dn);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
635 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
636
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
637 void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
638 dnode_setdirty(dnode_t *dn, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
639 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
640 objset_impl_t *os = dn->dn_objset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
641 uint64_t txg = tx->tx_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
642
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
643 if (dn->dn_object == DMU_META_DNODE_OBJECT)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
644 return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
645
873
adefbfa5f42d 6347448 non ZFS_DEBUG kernels shouldn't call empty verify functions
ek110237
parents: 789
diff changeset
646 DNODE_VERIFY(dn);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
647
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
648 #ifdef ZFS_DEBUG
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
649 mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
650 ASSERT(dn->dn_phys->dn_type || dn->dn_allocated_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
651 /* ASSERT(dn->dn_free_txg == 0 || dn->dn_free_txg >= txg); */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
652 mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
653 #endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
654
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
655 mutex_enter(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
656
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
657 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
658 * If we are already marked dirty, we're done.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
659 */
1596
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
660 if (list_link_active(&dn->dn_dirty_link[txg & TXG_MASK])) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
661 mutex_exit(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
662 return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
663 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
664
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
665 ASSERT(!refcount_is_zero(&dn->dn_holds) || list_head(&dn->dn_dbufs));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
666 ASSERT(dn->dn_datablksz != 0);
1599
b2940ec637b4 6397222 corrupt microzap object
ahrens
parents: 1596
diff changeset
667 ASSERT3U(dn->dn_next_blksz[txg&TXG_MASK], ==, 0);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
668
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
669 dprintf_ds(os->os_dsl_dataset, "obj=%llu txg=%llu\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
670 dn->dn_object, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
671
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
672 if (dn->dn_free_txg > 0 && dn->dn_free_txg <= txg) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
673 list_insert_tail(&os->os_free_dnodes[txg&TXG_MASK], dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
674 } else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
675 list_insert_tail(&os->os_dirty_dnodes[txg&TXG_MASK], dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
676 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
677
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
678 mutex_exit(&os->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
679
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
680 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
681 * The dnode maintains a hold on its containing dbuf as
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
682 * long as there are holds on it. Each instantiated child
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
683 * dbuf maintaines a hold on the dnode. When the last child
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
684 * drops its hold, the dnode will drop its hold on the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
685 * containing dbuf. We add a "dirty hold" here so that the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
686 * dnode will hang around after we finish processing its
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
687 * children.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
688 */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
689 dnode_add_ref(dn, (void *)(uintptr_t)tx->tx_txg);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
690
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
691 dbuf_dirty(dn->dn_dbuf, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
692
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
693 dsl_dataset_dirty(os->os_dsl_dataset, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
694 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
695
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
696 void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
697 dnode_free(dnode_t *dn, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
698 {
1596
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
699 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
700
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
701 dprintf("dn=%p txg=%llu\n", dn, tx->tx_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
702
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
703 /* we should be the only holder... hopefully */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
704 /* ASSERT3U(refcount_count(&dn->dn_holds), ==, 1); */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
705
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
706 mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
707 if (dn->dn_type == DMU_OT_NONE || dn->dn_free_txg) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
708 mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
709 return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
710 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
711 dn->dn_free_txg = tx->tx_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
712 mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
713
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
714 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
715 * If the dnode is already dirty, it needs to be moved from
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
716 * the dirty list to the free list.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
717 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
718 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
719 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
720 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
721 list_insert_tail(&dn->dn_objset->os_free_dnodes[txgoff], dn);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
722 mutex_exit(&dn->dn_objset->os_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
723 } else {
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 dnode_setdirty(dn, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
726 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
727 }
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 * Try to change the block size for the indicated dnode. This can only
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
731 * succeed if there are no blocks allocated or dirty beyond first block
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
732 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
733 int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
734 dnode_set_blksz(dnode_t *dn, uint64_t size, int ibs, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
735 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
736 dmu_buf_impl_t *db, *db_next;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
737 int have_db0 = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
738 int err = ENOTSUP;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
739
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
740 if (size == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
741 size = SPA_MINBLOCKSIZE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
742 if (size > SPA_MAXBLOCKSIZE)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
743 size = SPA_MAXBLOCKSIZE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
744 else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
745 size = P2ROUNDUP(size, SPA_MINBLOCKSIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
746
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
747 if (ibs == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
748 ibs = dn->dn_indblkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
749
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
750 if (size >> SPA_MINBLOCKSHIFT == dn->dn_datablkszsec &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
751 ibs == dn->dn_indblkshift)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
752 return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
753
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
754 rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
755
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
756 /* Check for any allocated blocks beyond the first */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
757 if (dn->dn_phys->dn_maxblkid != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
758 goto end;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
759
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
760 mutex_enter(&dn->dn_dbufs_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
761 for (db = list_head(&dn->dn_dbufs); db; db = db_next) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
762 db_next = list_next(&dn->dn_dbufs, db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
763
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
764 if (db->db_blkid == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
765 have_db0 = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
766 } else if (db->db_blkid != DB_BONUS_BLKID) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
767 mutex_exit(&dn->dn_dbufs_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
768 goto end;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
769 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
770 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
771 mutex_exit(&dn->dn_dbufs_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
772
1596
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
773 db = NULL;
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
774 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
775 /* obtain the old block */
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
776 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
777 dbuf_new_size(db, size, tx);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
778 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
779
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
780 dnode_setdblksz(dn, size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
781 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
782 dnode_setdirty(dn, tx);
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
783 dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = size;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
784 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
785
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
786 if (db)
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
787 dbuf_rele(db, FTAG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
788
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
789 err = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
790 end:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
791 rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
792 return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
793 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
794
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
795 uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
796 dnode_max_nonzero_offset(dnode_t *dn)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
797 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
798 if (dn->dn_phys->dn_maxblkid == 0 &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
799 BP_IS_HOLE(&dn->dn_phys->dn_blkptr[0]))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
800 return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
801 else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
802 return ((dn->dn_phys->dn_maxblkid+1) * dn->dn_datablksz);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
803 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
804
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
805 void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
806 dnode_new_blkid(dnode_t *dn, uint64_t blkid, dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
807 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
808 uint64_t txgoff = tx->tx_txg & TXG_MASK;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
809 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
810 int epbs, new_nlevels;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
811 uint64_t sz;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
812
1596
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
813 ASSERT(blkid != DB_BONUS_BLKID);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
814
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
815 if (!RW_WRITE_HELD(&dn->dn_struct_rwlock)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
816 rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
817 drop_struct_lock = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
818 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
819
1596
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
820 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
821 goto out;
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
822
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
823 dn->dn_maxblkid = blkid;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
824
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
825 /*
1596
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
826 * Compute the number of levels necessary to support the new maxblkid.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
827 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
828 new_nlevels = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
829 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
830 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
831 sz <= blkid && sz >= dn->dn_nblkptr; sz <<= epbs)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
832 new_nlevels++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
833
1596
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
834 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
835 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
836 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
837
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
838 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
839
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
840 ASSERT3U(new_nlevels, >, dn->dn_next_nlevels[txgoff]);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
841 dn->dn_next_nlevels[txgoff] = new_nlevels;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
842
1596
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
843 /* Dirty the left indirects. */
2e2377ccbf85 6395371 ASSERT in dmu_tx_count_free: blkid + i < dn->dn_phys->dn_nblkptr
ahrens
parents: 1544
diff changeset
844 db = dbuf_hold_level(dn, old_nlevels, 0, FTAG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
845 dbuf_dirty(db, tx);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
846 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
847
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
848 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
849
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
850 out:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
851 if (drop_struct_lock)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
852 rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
853 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
854
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
855 void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
856 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
857 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
858 avl_tree_t *tree = &dn->dn_ranges[tx->tx_txg&TXG_MASK];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
859 avl_index_t where;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
860 free_range_t *rp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
861 free_range_t rp_tofind;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
862 uint64_t endblk = blkid + nblks;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
863
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
864 ASSERT(MUTEX_HELD(&dn->dn_mtx));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
865 ASSERT(nblks <= UINT64_MAX - blkid); /* no overflow */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
866
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
867 dprintf_dnode(dn, "blkid=%llu nblks=%llu txg=%llu\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
868 blkid, nblks, tx->tx_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
869 rp_tofind.fr_blkid = blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
870 rp = avl_find(tree, &rp_tofind, &where);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
871 if (rp == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
872 rp = avl_nearest(tree, where, AVL_BEFORE);
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_AFTER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
875
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
876 while (rp && (rp->fr_blkid <= blkid + nblks)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
877 uint64_t fr_endblk = rp->fr_blkid + rp->fr_nblks;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
878 free_range_t *nrp = AVL_NEXT(tree, rp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
879
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
880 if (blkid <= rp->fr_blkid && endblk >= fr_endblk) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
881 /* clear this entire range */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
882 avl_remove(tree, rp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
883 kmem_free(rp, sizeof (free_range_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
884 } else if (blkid <= rp->fr_blkid &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
885 endblk > rp->fr_blkid && endblk < fr_endblk) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
886 /* clear the beginning of this range */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
887 rp->fr_blkid = endblk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
888 rp->fr_nblks = fr_endblk - endblk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
889 } else if (blkid > rp->fr_blkid && blkid < fr_endblk &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
890 endblk >= fr_endblk) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
891 /* clear the end of this range */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
892 rp->fr_nblks = blkid - rp->fr_blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
893 } else if (blkid > rp->fr_blkid && endblk < fr_endblk) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
894 /* clear a chunk out of this range */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
895 free_range_t *new_rp =
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
896 kmem_alloc(sizeof (free_range_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
897
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
898 new_rp->fr_blkid = endblk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
899 new_rp->fr_nblks = fr_endblk - endblk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
900 avl_insert_here(tree, new_rp, rp, AVL_AFTER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
901 rp->fr_nblks = blkid - rp->fr_blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
902 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
903 /* there may be no overlap */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
904 rp = nrp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
905 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
906 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
907
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
908 void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
909 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
910 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
911 dmu_buf_impl_t *db;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
912 uint64_t start, objsize, blkid, nblks;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
913 int blkshift, blksz, tail, head, epbs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
914 int trunc = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
915
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
916 rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
917 blksz = dn->dn_datablksz;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
918 blkshift = dn->dn_datablkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
919 epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
920
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
921 /* If the range is past the end of the file, this is a no-op */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
922 objsize = blksz * (dn->dn_maxblkid+1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
923 if (off >= objsize)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
924 goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
925 if (len == -1ULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
926 len = UINT64_MAX - off;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
927 trunc = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
928 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
929
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
930 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
931 * First, block align the region to free:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
932 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
933 if (dn->dn_maxblkid == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
934 if (off == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
935 head = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
936 } else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
937 head = blksz - off;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
938 ASSERT3U(head, >, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
939 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
940 start = off;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
941 } else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
942 ASSERT(ISP2(blksz));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
943 head = P2NPHASE(off, blksz);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
944 start = P2PHASE(off, blksz);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
945 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
946 /* zero out any partial block data at the start of the range */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
947 if (head) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
948 ASSERT3U(start + head, ==, blksz);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
949 if (len < head)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
950 head = len;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
951 if (dbuf_hold_impl(dn, 0, dbuf_whichblock(dn, off), TRUE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
952 FTAG, &db) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
953 caddr_t data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
954
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
955 /* don't dirty if it isn't on disk and isn't dirty */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
956 if (db->db_dirtied ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
957 (db->db_blkptr && !BP_IS_HOLE(db->db_blkptr))) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
958 rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
959 dbuf_will_dirty(db, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
960 rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
961 data = db->db.db_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
962 bzero(data + start, head);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
963 }
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
964 dbuf_rele(db, FTAG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
965 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
966 off += head;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
967 len -= head;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
968 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
969 /* If the range was less than one block, we are done */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
970 if (len == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
971 goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
972
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
973 /* If the remaining range is past the end of the file, we are done */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
974 if (off > dn->dn_maxblkid << blkshift)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
975 goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
976
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
977 if (off + len == UINT64_MAX)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
978 tail = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
979 else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
980 tail = P2PHASE(len, blksz);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
981
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
982 ASSERT3U(P2PHASE(off, blksz), ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
983 /* zero out any partial block data at the end of the range */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
984 if (tail) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
985 if (len < tail)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
986 tail = len;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
987 if (dbuf_hold_impl(dn, 0, dbuf_whichblock(dn, off+len),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
988 TRUE, FTAG, &db) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
989 /* don't dirty if it isn't on disk and isn't dirty */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
990 if (db->db_dirtied ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
991 (db->db_blkptr && !BP_IS_HOLE(db->db_blkptr))) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
992 rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
993 dbuf_will_dirty(db, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
994 rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
995 bzero(db->db.db_data, tail);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
996 }
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
997 dbuf_rele(db, FTAG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
998 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
999 len -= tail;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1000 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1001 /* If the range did not include a full block, we are done */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1002 if (len == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1003 goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1004
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1005 /* dirty the left indirects */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1006 if (dn->dn_nlevels > 1 && off != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1007 db = dbuf_hold_level(dn, 1,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1008 (off - head) >> (blkshift + epbs), FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1009 dbuf_will_dirty(db, tx);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
1010 dbuf_rele(db, FTAG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1011 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1012
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1013 /* dirty the right indirects */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1014 if (dn->dn_nlevels > 1 && !trunc) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1015 db = dbuf_hold_level(dn, 1,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1016 (off + len + tail - 1) >> (blkshift + epbs), FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1017 dbuf_will_dirty(db, tx);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
1018 dbuf_rele(db, FTAG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1019 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1020
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1021 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1022 * Finally, add this range to the dnode range list, we
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1023 * will finish up this free operation in the syncing phase.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1024 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1025 ASSERT(IS_P2ALIGNED(off, 1<<blkshift));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1026 ASSERT(off + len == UINT64_MAX || IS_P2ALIGNED(len, 1<<blkshift));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1027 blkid = off >> blkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1028 nblks = len >> blkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1029
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1030 if (trunc)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1031 dn->dn_maxblkid = (blkid ? blkid - 1 : 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1032
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1033 mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1034 dnode_clear_range(dn, blkid, nblks, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1035 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1036 free_range_t *rp, *found;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1037 avl_index_t where;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1038 avl_tree_t *tree = &dn->dn_ranges[tx->tx_txg&TXG_MASK];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1039
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1040 /* Add new range to dn_ranges */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1041 rp = kmem_alloc(sizeof (free_range_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1042 rp->fr_blkid = blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1043 rp->fr_nblks = nblks;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1044 found = avl_find(tree, rp, &where);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1045 ASSERT(found == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1046 avl_insert(tree, rp, where);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1047 dprintf_dnode(dn, "blkid=%llu nblks=%llu txg=%llu\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1048 blkid, nblks, tx->tx_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1049 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1050 mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1051
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1052 dbuf_free_range(dn, blkid, nblks, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1053 dnode_setdirty(dn, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1054 out:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1055 rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1056 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1057
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1058 /* 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
1059 uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1060 dnode_block_freed(dnode_t *dn, uint64_t blkid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1061 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1062 free_range_t range_tofind;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1063 void *dp = spa_get_dsl(dn->dn_objset->os_spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1064 int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1065
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1066 if (blkid == DB_BONUS_BLKID)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1067 return (FALSE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1068
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1069 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1070 * If we're in the process of opening the pool, dp will not be
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1071 * set yet, but there shouldn't be anything dirty.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1072 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1073 if (dp == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1074 return (FALSE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1075
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1076 if (dn->dn_free_txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1077 return (TRUE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1078
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1079 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1080 * If dn_datablkshift is not set, then there's only a single
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1081 * block, in which case there will never be a free range so it
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1082 * won't matter.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1083 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1084 range_tofind.fr_blkid = blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1085 mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1086 for (i = 0; i < TXG_SIZE; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1087 free_range_t *range_found;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1088 avl_index_t idx;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1089
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1090 range_found = avl_find(&dn->dn_ranges[i], &range_tofind, &idx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1091 if (range_found) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1092 ASSERT(range_found->fr_nblks > 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1093 break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1094 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1095 range_found = avl_nearest(&dn->dn_ranges[i], idx, AVL_BEFORE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1096 if (range_found &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1097 range_found->fr_blkid + range_found->fr_nblks > blkid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1098 break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1099 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1100 mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1101 return (i < TXG_SIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1102 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1103
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1104 /* call from syncing context when we actually write/free space for this dnode */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1105 void
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1106 dnode_diduse_space(dnode_t *dn, int64_t delta)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1107 {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1108 uint64_t space;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1109 dprintf_dnode(dn, "dn=%p dnp=%p used=%llu delta=%lld\n",
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1110 dn, dn->dn_phys,
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1111 (u_longlong_t)dn->dn_phys->dn_used,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1112 (longlong_t)delta);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1113
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1114 mutex_enter(&dn->dn_mtx);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1115 space = DN_USED_BYTES(dn->dn_phys);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1116 if (delta > 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1117 ASSERT3U(space + delta, >=, space); /* no overflow */
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1118 } else {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1119 ASSERT3U(space, >=, -delta); /* no underflow */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1120 }
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1121 space += delta;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1122 if (spa_version(dn->dn_objset->os_spa) < ZFS_VERSION_DNODE_BYTES) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1123 ASSERT((dn->dn_phys->dn_flags & DNODE_FLAG_USED_BYTES) == 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1124 ASSERT3U(P2PHASE(space, 1<<DEV_BSHIFT), ==, 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1125 dn->dn_phys->dn_used = space >> DEV_BSHIFT;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1126 } else {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1127 dn->dn_phys->dn_used = space;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1990
diff changeset
1128 dn->dn_phys->dn_flags |= DNODE_FLAG_USED_BYTES;
789
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 }
1793
d371fba21a3e 6407444 unhandled i/o error from dnode_next_offset_level()
ahrens
parents: 1646
diff changeset
1179 error = dbuf_read(db, NULL, DB_RF_CANFAIL | DB_RF_HAVESTRUCT);
d371fba21a3e 6407444 unhandled i/o error from dnode_next_offset_level()
ahrens
parents: 1646
diff changeset
1180 if (error) {
d371fba21a3e 6407444 unhandled i/o error from dnode_next_offset_level()
ahrens
parents: 1646
diff changeset
1181 dbuf_rele(db, FTAG);
d371fba21a3e 6407444 unhandled i/o error from dnode_next_offset_level()
ahrens
parents: 1646
diff changeset
1182 return (error);
d371fba21a3e 6407444 unhandled i/o error from dnode_next_offset_level()
ahrens
parents: 1646
diff changeset
1183 }
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1184 data = db->db.db_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1185 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1186
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1187 if (lvl == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1188 dnode_phys_t *dnp = data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1189 span = DNODE_SHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1190 ASSERT(dn->dn_type == DMU_OT_DNODE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1191
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1192 for (i = (*offset >> span) & (blkfill - 1); i < blkfill; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1193 if (!dnp[i].dn_type == hole)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1194 break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1195 *offset += 1ULL << span;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1196 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1197 if (i == blkfill)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1198 error = ESRCH;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1199 } else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1200 blkptr_t *bp = data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1201 span = (lvl - 1) * epbs + dn->dn_datablkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1202 minfill = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1203 maxfill = blkfill << ((lvl - 1) * epbs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1204
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1205 if (hole)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1206 maxfill--;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1207 else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1208 minfill++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1209
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1210 for (i = (*offset >> span) & ((1ULL << epbs) - 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1211 i < epb; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1212 if (bp[i].blk_fill >= minfill &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1213 bp[i].blk_fill <= maxfill)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1214 break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1215 *offset += 1ULL << span;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1216 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1217 if (i >= epb)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1218 error = ESRCH;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1219 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1220
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1221 if (db)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1491
diff changeset
1222 dbuf_rele(db, FTAG);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1223
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1224 return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1225 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1226
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1227 /*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1228 * Find the next hole, data, or sparse region at or after *offset.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1229 * The value 'blkfill' tells us how many items we expect to find
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1230 * in an L0 data block; this value is 1 for normal objects,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1231 * DNODES_PER_BLOCK for the meta dnode, and some fraction of
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1232 * DNODES_PER_BLOCK when searching for sparse regions thereof.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1233 * Examples:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1234 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1235 * dnode_next_offset(dn, hole, offset, 1, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1236 * Finds the next hole/data in a file.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1237 * Used in dmu_offset_next().
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1238 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1239 * dnode_next_offset(mdn, hole, offset, 0, DNODES_PER_BLOCK);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1240 * Finds the next free/allocated dnode an objset's meta-dnode.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1241 * Used in dmu_object_next().
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1242 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1243 * dnode_next_offset(mdn, TRUE, offset, 2, DNODES_PER_BLOCK >> 2);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1244 * Finds the next L2 meta-dnode bp that's at most 1/4 full.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1245 * Used in dmu_object_alloc().
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1246 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1247 int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1248 dnode_next_offset(dnode_t *dn, boolean_t hole, uint64_t *offset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1249 int minlvl, uint64_t blkfill)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1250 {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1251 int lvl, maxlvl;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1252 int error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1253 uint64_t initial_offset = *offset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1254
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1255 rw_enter(&dn->dn_struct_rwlock, RW_READER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1256
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1257 if (dn->dn_phys->dn_nlevels == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1258 rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1259 return (ESRCH);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1260 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1261
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1262 if (dn->dn_datablkshift == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1263 if (*offset < dn->dn_datablksz) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1264 if (hole)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1265 *offset = dn->dn_datablksz;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1266 } else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1267 error = ESRCH;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1268 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1269 rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1270 return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1271 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1272
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1273 maxlvl = dn->dn_phys->dn_nlevels;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1274
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1275 for (lvl = minlvl; lvl <= maxlvl; lvl++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1276 error = dnode_next_offset_level(dn, hole, offset, lvl, blkfill);
1793
d371fba21a3e 6407444 unhandled i/o error from dnode_next_offset_level()
ahrens
parents: 1646
diff changeset
1277 if (error != ESRCH)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1278 break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1279 }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1280
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1281 while (--lvl >= minlvl && error == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1282 error = dnode_next_offset_level(dn, hole, offset, lvl, blkfill);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1283
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1284 rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1285
1793
d371fba21a3e 6407444 unhandled i/o error from dnode_next_offset_level()
ahrens
parents: 1646
diff changeset
1286 if (error == 0 && initial_offset > *offset)
d371fba21a3e 6407444 unhandled i/o error from dnode_next_offset_level()
ahrens
parents: 1646
diff changeset
1287 error = ESRCH;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1288
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1289 return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
1290 }