Deleted Added
sdiff udiff text old ( 209093 ) new ( 209962 )
full compact
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

--- 5 unchanged lines hidden (view full) ---

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/*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <sys/dmu.h>
27#include <sys/dmu_impl.h>
28#include <sys/dbuf.h>
29#include <sys/dmu_tx.h>
30#include <sys/dmu_objset.h>

--- 124 unchanged lines hidden (view full) ---

155 rw_exit(&dn->dn_struct_rwlock);
156 if (db == NULL)
157 return (EIO);
158 err = dbuf_read(db, zio, DB_RF_CANFAIL | DB_RF_NOPREFETCH);
159 dbuf_rele(db, FTAG);
160 return (err);
161}
162
163/* ARGSUSED */
164static void
165dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
166{
167 dnode_t *dn = txh->txh_dnode;
168 uint64_t start, end, i;
169 int min_bs, max_bs, min_ibs, max_ibs, epbs, bits;
170 int err = 0;
171
172 if (len == 0)
173 return;
174
175 min_bs = SPA_MINBLOCKSHIFT;
176 max_bs = SPA_MAXBLOCKSHIFT;
177 min_ibs = DN_MIN_INDBLKSHIFT;
178 max_ibs = DN_MAX_INDBLKSHIFT;
179
180
181 /*
182 * For i/o error checking, read the first and last level-0
183 * blocks (if they are not aligned), and all the level-1 blocks.
184 */
185
186 if (dn) {
187 if (dn->dn_maxblkid == 0) {
188 err = dmu_tx_check_ioerr(NULL, dn, 0, 0);
189 if (err)
190 goto out;
191 } else {
192 zio_t *zio = zio_root(dn->dn_objset->os_spa,
193 NULL, NULL, ZIO_FLAG_CANFAIL);
194
195 /* first level-0 block */
196 start = off >> dn->dn_datablkshift;
197 if (P2PHASE(off, dn->dn_datablksz) ||
198 len < dn->dn_datablksz) {

--- 7 unchanged lines hidden (view full) ---

206 if (end != start &&
207 P2PHASE(off+len, dn->dn_datablksz)) {
208 err = dmu_tx_check_ioerr(zio, dn, 0, end);
209 if (err)
210 goto out;
211 }
212
213 /* level-1 blocks */
214 if (dn->dn_nlevels > 1) {
215 start >>= dn->dn_indblkshift - SPA_BLKPTRSHIFT;
216 end >>= dn->dn_indblkshift - SPA_BLKPTRSHIFT;
217 for (i = start+1; i < end; i++) {
218 err = dmu_tx_check_ioerr(zio, dn, 1, i);
219 if (err)
220 goto out;
221 }
222 }
223
224 err = zio_wait(zio);
225 if (err)
226 goto out;
227 }
228 }
229
230 /*
231 * If there's more than one block, the blocksize can't change,
232 * so we can make a more precise estimate. Alternatively,
233 * if the dnode's ibs is larger than max_ibs, always use that.
234 * This ensures that if we reduce DN_MAX_INDBLKSHIFT,
235 * the code will still work correctly on existing pools.
236 */
237 if (dn && (dn->dn_maxblkid != 0 || dn->dn_indblkshift > max_ibs)) {
238 min_ibs = max_ibs = dn->dn_indblkshift;
239 if (dn->dn_datablkshift != 0)
240 min_bs = max_bs = dn->dn_datablkshift;
241 }
242
243 /*
244 * 'end' is the last thing we will access, not one past.
245 * This way we won't overflow when accessing the last byte.
246 */
247 start = P2ALIGN(off, 1ULL << max_bs);
248 end = P2ROUNDUP(off + len, 1ULL << max_bs) - 1;

--- 6 unchanged lines hidden (view full) ---

255
256 /*
257 * The object contains at most 2^(64 - min_bs) blocks,
258 * and each indirect level maps 2^epbs.
259 */
260 for (bits = 64 - min_bs; bits >= 0; bits -= epbs) {
261 start >>= epbs;
262 end >>= epbs;
263 /*
264 * If we increase the number of levels of indirection,
265 * we'll need new blkid=0 indirect blocks. If start == 0,
266 * we're already accounting for that blocks; and if end == 0,
267 * we can't increase the number of levels beyond that.
268 */
269 if (start != 0 && end != 0)
270 txh->txh_space_towrite += 1ULL << max_ibs;
271 txh->txh_space_towrite += (end - start + 1) << max_ibs;
272 }
273
274 ASSERT(txh->txh_space_towrite < 2 * DMU_MAX_ACCESS);
275
276out:
277 if (err)
278 txh->txh_tx->tx_err = err;
279}
280
281static void
282dmu_tx_count_dnode(dmu_tx_hold_t *txh)
283{
284 dnode_t *dn = txh->txh_dnode;
285 dnode_t *mdn = txh->txh_tx->tx_objset->os->os_meta_dnode;
286 uint64_t space = mdn->dn_datablksz +
287 ((mdn->dn_nlevels-1) << mdn->dn_indblkshift);
288
289 if (dn && dn->dn_dbuf->db_blkptr &&
290 dsl_dataset_block_freeable(dn->dn_objset->os_dsl_dataset,
291 dn->dn_dbuf->db_blkptr->blk_birth)) {
292 txh->txh_space_tooverwrite += space;
293 } else {
294 txh->txh_space_towrite += space;
295 if (dn && dn->dn_dbuf->db_blkptr)
296 txh->txh_space_tounref += space;
297 }
298}
299
300void

--- 227 unchanged lines hidden (view full) ---

528 }
529 }
530
531 dmu_tx_count_dnode(txh);
532 dmu_tx_count_free(txh, off, len);
533}
534
535void
536dmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int add, char *name)
537{
538 dmu_tx_hold_t *txh;
539 dnode_t *dn;
540 uint64_t nblocks;
541 int epbs, err;
542
543 ASSERT(tx->tx_txg == 0);
544

--- 51 unchanged lines hidden (view full) ---

596 err = zap_lookup(&dn->dn_objset->os, dn->dn_object, name,
597 8, 0, NULL);
598 if (err == EIO) {
599 tx->tx_err = err;
600 return;
601 }
602 }
603
604 /*
605 * 3 blocks overwritten: target leaf, ptrtbl block, header block
606 * 3 new blocks written if adding: new split leaf, 2 grown ptrtbl blocks
607 */
608 dmu_tx_count_write(txh, dn->dn_maxblkid * dn->dn_datablksz,
609 (3 + (add ? 3 : 0)) << dn->dn_datablkshift);
610
611 /*
612 * If the modified blocks are scattered to the four winds,
613 * we'll have to modify an indirect twig for each.
614 */
615 epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
616 for (nblocks = dn->dn_maxblkid >> epbs; nblocks != 0; nblocks >>= epbs)
617 txh->txh_space_towrite += 3 << dn->dn_indblkshift;
618}
619
620void
621dmu_tx_hold_bonus(dmu_tx_t *tx, uint64_t object)
622{
623 dmu_tx_hold_t *txh;
624
625 ASSERT(tx->tx_txg == 0);

--- 441 unchanged lines hidden ---