]>
Commit | Line | Data |
---|---|---|
34dc7c2f BB |
1 | /* |
2 | * CDDL HEADER START | |
3 | * | |
4 | * The contents of this file are subject to the terms of the | |
5 | * Common Development and Distribution License (the "License"). | |
6 | * You may not use this file except in compliance with the License. | |
7 | * | |
8 | * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
9 | * or http://www.opensolaris.org/os/licensing. | |
10 | * See the License for the specific language governing permissions | |
11 | * and limitations under the License. | |
12 | * | |
13 | * When distributing Covered Code, include this CDDL HEADER in each | |
14 | * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
15 | * If applicable, add the following below this CDDL HEADER, with the | |
16 | * fields enclosed by brackets "[]" replaced with your own identifying | |
17 | * information: Portions Copyright [yyyy] [name of copyright owner] | |
18 | * | |
19 | * CDDL HEADER END | |
20 | */ | |
21 | /* | |
428870ff | 22 | * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
ea04106b AX |
23 | * Copyright (c) 2013, 2014 by Delphix. All rights reserved. |
24 | * Copyright 2014 HybridCluster. All rights reserved. | |
34dc7c2f BB |
25 | */ |
26 | ||
34dc7c2f BB |
27 | #include <sys/dmu.h> |
28 | #include <sys/dmu_objset.h> | |
29 | #include <sys/dmu_tx.h> | |
30 | #include <sys/dnode.h> | |
ea04106b AX |
31 | #include <sys/zap.h> |
32 | #include <sys/zfeature.h> | |
34dc7c2f BB |
33 | |
34 | uint64_t | |
35 | dmu_object_alloc(objset_t *os, dmu_object_type_t ot, int blocksize, | |
36 | dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) | |
37 | { | |
34dc7c2f BB |
38 | uint64_t object; |
39 | uint64_t L2_dnode_count = DNODES_PER_BLOCK << | |
572e2857 | 40 | (DMU_META_DNODE(os)->dn_indblkshift - SPA_BLKPTRSHIFT); |
34dc7c2f BB |
41 | dnode_t *dn = NULL; |
42 | int restarted = B_FALSE; | |
43 | ||
428870ff | 44 | mutex_enter(&os->os_obj_lock); |
34dc7c2f | 45 | for (;;) { |
428870ff | 46 | object = os->os_obj_next; |
34dc7c2f BB |
47 | /* |
48 | * Each time we polish off an L2 bp worth of dnodes | |
49 | * (2^13 objects), move to another L2 bp that's still | |
50 | * reasonably sparse (at most 1/4 full). Look from the | |
51 | * beginning once, but after that keep looking from here. | |
52 | * If we can't find one, just keep going from here. | |
53 | */ | |
54 | if (P2PHASE(object, L2_dnode_count) == 0) { | |
55 | uint64_t offset = restarted ? object << DNODE_SHIFT : 0; | |
572e2857 | 56 | int error = dnode_next_offset(DMU_META_DNODE(os), |
b128c09f BB |
57 | DNODE_FIND_HOLE, |
58 | &offset, 2, DNODES_PER_BLOCK >> 2, 0); | |
34dc7c2f BB |
59 | restarted = B_TRUE; |
60 | if (error == 0) | |
61 | object = offset >> DNODE_SHIFT; | |
62 | } | |
428870ff | 63 | os->os_obj_next = ++object; |
34dc7c2f BB |
64 | |
65 | /* | |
66 | * XXX We should check for an i/o error here and return | |
67 | * up to our caller. Actually we should pre-read it in | |
68 | * dmu_tx_assign(), but there is currently no mechanism | |
69 | * to do so. | |
70 | */ | |
428870ff | 71 | (void) dnode_hold_impl(os, object, DNODE_MUST_BE_FREE, |
34dc7c2f BB |
72 | FTAG, &dn); |
73 | if (dn) | |
74 | break; | |
75 | ||
76 | if (dmu_object_next(os, &object, B_TRUE, 0) == 0) | |
428870ff | 77 | os->os_obj_next = object - 1; |
34dc7c2f BB |
78 | } |
79 | ||
80 | dnode_allocate(dn, ot, blocksize, 0, bonustype, bonuslen, tx); | |
81 | dnode_rele(dn, FTAG); | |
82 | ||
428870ff | 83 | mutex_exit(&os->os_obj_lock); |
34dc7c2f BB |
84 | |
85 | dmu_tx_add_new_object(tx, os, object); | |
86 | return (object); | |
87 | } | |
88 | ||
89 | int | |
90 | dmu_object_claim(objset_t *os, uint64_t object, dmu_object_type_t ot, | |
91 | int blocksize, dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) | |
92 | { | |
93 | dnode_t *dn; | |
94 | int err; | |
95 | ||
96 | if (object == DMU_META_DNODE_OBJECT && !dmu_tx_private_ok(tx)) | |
a08ee875 | 97 | return (SET_ERROR(EBADF)); |
34dc7c2f | 98 | |
428870ff | 99 | err = dnode_hold_impl(os, object, DNODE_MUST_BE_FREE, FTAG, &dn); |
34dc7c2f BB |
100 | if (err) |
101 | return (err); | |
102 | dnode_allocate(dn, ot, blocksize, 0, bonustype, bonuslen, tx); | |
103 | dnode_rele(dn, FTAG); | |
104 | ||
105 | dmu_tx_add_new_object(tx, os, object); | |
106 | return (0); | |
107 | } | |
108 | ||
109 | int | |
110 | dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot, | |
ea04106b | 111 | int blocksize, dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) |
34dc7c2f BB |
112 | { |
113 | dnode_t *dn; | |
114 | int err; | |
115 | ||
9babb374 | 116 | if (object == DMU_META_DNODE_OBJECT) |
a08ee875 | 117 | return (SET_ERROR(EBADF)); |
34dc7c2f | 118 | |
428870ff | 119 | err = dnode_hold_impl(os, object, DNODE_MUST_BE_ALLOCATED, |
34dc7c2f BB |
120 | FTAG, &dn); |
121 | if (err) | |
122 | return (err); | |
9babb374 | 123 | |
34dc7c2f | 124 | dnode_reallocate(dn, ot, blocksize, bonustype, bonuslen, tx); |
9babb374 | 125 | |
34dc7c2f | 126 | dnode_rele(dn, FTAG); |
9babb374 | 127 | return (err); |
34dc7c2f BB |
128 | } |
129 | ||
130 | int | |
131 | dmu_object_free(objset_t *os, uint64_t object, dmu_tx_t *tx) | |
132 | { | |
133 | dnode_t *dn; | |
134 | int err; | |
135 | ||
136 | ASSERT(object != DMU_META_DNODE_OBJECT || dmu_tx_private_ok(tx)); | |
137 | ||
428870ff | 138 | err = dnode_hold_impl(os, object, DNODE_MUST_BE_ALLOCATED, |
34dc7c2f BB |
139 | FTAG, &dn); |
140 | if (err) | |
141 | return (err); | |
142 | ||
143 | ASSERT(dn->dn_type != DMU_OT_NONE); | |
b128c09f | 144 | dnode_free_range(dn, 0, DMU_OBJECT_END, tx); |
34dc7c2f BB |
145 | dnode_free(dn, tx); |
146 | dnode_rele(dn, FTAG); | |
147 | ||
148 | return (0); | |
149 | } | |
150 | ||
151 | int | |
152 | dmu_object_next(objset_t *os, uint64_t *objectp, boolean_t hole, uint64_t txg) | |
153 | { | |
154 | uint64_t offset = (*objectp + 1) << DNODE_SHIFT; | |
155 | int error; | |
156 | ||
572e2857 | 157 | error = dnode_next_offset(DMU_META_DNODE(os), |
b128c09f | 158 | (hole ? DNODE_FIND_HOLE : 0), &offset, 0, DNODES_PER_BLOCK, txg); |
34dc7c2f BB |
159 | |
160 | *objectp = offset >> DNODE_SHIFT; | |
161 | ||
162 | return (error); | |
163 | } | |
c28b2279 | 164 | |
ea04106b AX |
165 | /* |
166 | * Turn this object from old_type into DMU_OTN_ZAP_METADATA, and bump the | |
167 | * refcount on SPA_FEATURE_EXTENSIBLE_DATASET. | |
168 | * | |
169 | * Only for use from syncing context, on MOS objects. | |
170 | */ | |
171 | void | |
172 | dmu_object_zapify(objset_t *mos, uint64_t object, dmu_object_type_t old_type, | |
173 | dmu_tx_t *tx) | |
174 | { | |
175 | dnode_t *dn; | |
176 | ||
177 | ASSERT(dmu_tx_is_syncing(tx)); | |
178 | ||
179 | VERIFY0(dnode_hold(mos, object, FTAG, &dn)); | |
180 | if (dn->dn_type == DMU_OTN_ZAP_METADATA) { | |
181 | dnode_rele(dn, FTAG); | |
182 | return; | |
183 | } | |
184 | ASSERT3U(dn->dn_type, ==, old_type); | |
185 | ASSERT0(dn->dn_maxblkid); | |
186 | dn->dn_next_type[tx->tx_txg & TXG_MASK] = dn->dn_type = | |
187 | DMU_OTN_ZAP_METADATA; | |
188 | dnode_setdirty(dn, tx); | |
189 | dnode_rele(dn, FTAG); | |
190 | ||
191 | mzap_create_impl(mos, object, 0, 0, tx); | |
192 | ||
193 | spa_feature_incr(dmu_objset_spa(mos), | |
194 | SPA_FEATURE_EXTENSIBLE_DATASET, tx); | |
195 | } | |
196 | ||
197 | void | |
198 | dmu_object_free_zapified(objset_t *mos, uint64_t object, dmu_tx_t *tx) | |
199 | { | |
200 | dnode_t *dn; | |
201 | dmu_object_type_t t; | |
202 | ||
203 | ASSERT(dmu_tx_is_syncing(tx)); | |
204 | ||
205 | VERIFY0(dnode_hold(mos, object, FTAG, &dn)); | |
206 | t = dn->dn_type; | |
207 | dnode_rele(dn, FTAG); | |
208 | ||
209 | if (t == DMU_OTN_ZAP_METADATA) { | |
210 | spa_feature_decr(dmu_objset_spa(mos), | |
211 | SPA_FEATURE_EXTENSIBLE_DATASET, tx); | |
212 | } | |
213 | VERIFY0(dmu_object_free(mos, object, tx)); | |
214 | } | |
215 | ||
c28b2279 BB |
216 | #if defined(_KERNEL) && defined(HAVE_SPL) |
217 | EXPORT_SYMBOL(dmu_object_alloc); | |
218 | EXPORT_SYMBOL(dmu_object_claim); | |
219 | EXPORT_SYMBOL(dmu_object_reclaim); | |
220 | EXPORT_SYMBOL(dmu_object_free); | |
221 | EXPORT_SYMBOL(dmu_object_next); | |
ea04106b AX |
222 | EXPORT_SYMBOL(dmu_object_zapify); |
223 | EXPORT_SYMBOL(dmu_object_free_zapified); | |
c28b2279 | 224 | #endif |