Deleted Added
full compact
dmu_tx.c (209093) dmu_tx.c (209962)
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/*
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.
22 * Copyright 2009 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
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
163static void
164dmu_tx_count_indirects(dmu_tx_hold_t *txh, dmu_buf_impl_t *db,
165 boolean_t freeable, dmu_buf_impl_t **history)
166{
167 int i = db->db_level + 1;
168 dnode_t *dn = db->db_dnode;
169
170 if (i >= dn->dn_nlevels)
171 return;
172
173 db = db->db_parent;
174 if (db == NULL) {
175 uint64_t lvls = dn->dn_nlevels - i;
176
177 txh->txh_space_towrite += lvls << dn->dn_indblkshift;
178 return;
179 }
180
181 if (db != history[i]) {
182 dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset;
183 uint64_t space = 1ULL << dn->dn_indblkshift;
184
185 freeable = (db->db_blkptr && (freeable ||
186 dsl_dataset_block_freeable(ds, db->db_blkptr->blk_birth)));
187 if (freeable)
188 txh->txh_space_tooverwrite += space;
189 else
190 txh->txh_space_towrite += space;
191 if (db->db_blkptr)
192 txh->txh_space_tounref += space;
193 history[i] = db;
194 dmu_tx_count_indirects(txh, db, freeable, history);
195 }
196}
197
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
198/* ARGSUSED */
199static void
200dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
201{
202 dnode_t *dn = txh->txh_dnode;
203 uint64_t start, end, i;
204 int min_bs, max_bs, min_ibs, max_ibs, epbs, bits;
205 int err = 0;
206
207 if (len == 0)
208 return;
209
210 min_bs = SPA_MINBLOCKSHIFT;
211 max_bs = SPA_MAXBLOCKSHIFT;
212 min_ibs = DN_MIN_INDBLKSHIFT;
213 max_ibs = DN_MAX_INDBLKSHIFT;
214
215 if (dn) {
216 dmu_buf_impl_t *last[DN_MAX_LEVELS];
217 int nlvls = dn->dn_nlevels;
218 int delta;
180
219
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 */
220 /*
221 * For i/o error checking, read the first and last level-0
222 * blocks (if they are not aligned), and all the level-1 blocks.
223 */
185
224
186 if (dn) {
187 if (dn->dn_maxblkid == 0) {
225 if (dn->dn_maxblkid == 0) {
188 err = dmu_tx_check_ioerr(NULL, dn, 0, 0);
189 if (err)
190 goto out;
226 delta = dn->dn_datablksz;
227 start = (off < dn->dn_datablksz) ? 0 : 1;
228 end = (off+len <= dn->dn_datablksz) ? 0 : 1;
229 if (start == 0 && (off > 0 || len < dn->dn_datablksz)) {
230 err = dmu_tx_check_ioerr(NULL, dn, 0, 0);
231 if (err)
232 goto out;
233 delta -= off;
234 }
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 */
235 } else {
236 zio_t *zio = zio_root(dn->dn_objset->os_spa,
237 NULL, NULL, ZIO_FLAG_CANFAIL);
238
239 /* first level-0 block */
240 start = off >> dn->dn_datablkshift;
241 if (P2PHASE(off, dn->dn_datablksz) ||
242 len < dn->dn_datablksz) {

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

250 if (end != start &&
251 P2PHASE(off+len, dn->dn_datablksz)) {
252 err = dmu_tx_check_ioerr(zio, dn, 0, end);
253 if (err)
254 goto out;
255 }
256
257 /* 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++) {
258 if (nlvls > 1) {
259 int shft = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
260 for (i = (start>>shft)+1; i < end>>shft; 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;
261 err = dmu_tx_check_ioerr(zio, dn, 1, i);
262 if (err)
263 goto out;
264 }
265 }
266
267 err = zio_wait(zio);
268 if (err)
269 goto out;
270 delta = P2NPHASE(off, dn->dn_datablksz);
227 }
271 }
228 }
229
272
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)
273 if (dn->dn_maxblkid > 0) {
274 /*
275 * The blocksize can't change,
276 * so we can make a more precise estimate.
277 */
278 ASSERT(dn->dn_datablkshift != 0);
240 min_bs = max_bs = dn->dn_datablkshift;
279 min_bs = max_bs = dn->dn_datablkshift;
280 min_ibs = max_ibs = dn->dn_indblkshift;
281 } else if (dn->dn_indblkshift > max_ibs) {
282 /*
283 * This ensures that if we reduce DN_MAX_INDBLKSHIFT,
284 * the code will still work correctly on older pools.
285 */
286 min_ibs = max_ibs = dn->dn_indblkshift;
287 }
288
289 /*
290 * If this write is not off the end of the file
291 * we need to account for overwrites/unref.
292 */
293 if (start <= dn->dn_maxblkid)
294 bzero(last, sizeof (dmu_buf_impl_t *) * DN_MAX_LEVELS);
295 while (start <= dn->dn_maxblkid) {
296 spa_t *spa = txh->txh_tx->tx_pool->dp_spa;
297 dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset;
298 dmu_buf_impl_t *db;
299
300 rw_enter(&dn->dn_struct_rwlock, RW_READER);
301 db = dbuf_hold_level(dn, 0, start, FTAG);
302 rw_exit(&dn->dn_struct_rwlock);
303 if (db->db_blkptr && dsl_dataset_block_freeable(ds,
304 db->db_blkptr->blk_birth)) {
305 dprintf_bp(db->db_blkptr, "can free old%s", "");
306 txh->txh_space_tooverwrite += dn->dn_datablksz;
307 txh->txh_space_tounref += dn->dn_datablksz;
308 dmu_tx_count_indirects(txh, db, TRUE, last);
309 } else {
310 txh->txh_space_towrite += dn->dn_datablksz;
311 if (db->db_blkptr)
312 txh->txh_space_tounref +=
313 bp_get_dasize(spa, db->db_blkptr);
314 dmu_tx_count_indirects(txh, db, FALSE, last);
315 }
316 dbuf_rele(db, FTAG);
317 if (++start > end) {
318 /*
319 * Account for new indirects appearing
320 * before this IO gets assigned into a txg.
321 */
322 bits = 64 - min_bs;
323 epbs = min_ibs - SPA_BLKPTRSHIFT;
324 for (bits -= epbs * (nlvls - 1);
325 bits >= 0; bits -= epbs)
326 txh->txh_fudge += 1ULL << max_ibs;
327 goto out;
328 }
329 off += delta;
330 if (len >= delta)
331 len -= delta;
332 delta = dn->dn_datablksz;
333 }
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;
334 }
335
336 /*
337 * 'end' is the last thing we will access, not one past.
338 * This way we won't overflow when accessing the last byte.
339 */
340 start = P2ALIGN(off, 1ULL << max_bs);
341 end = P2ROUNDUP(off + len, 1ULL << max_bs) - 1;

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

348
349 /*
350 * The object contains at most 2^(64 - min_bs) blocks,
351 * and each indirect level maps 2^epbs.
352 */
353 for (bits = 64 - min_bs; bits >= 0; bits -= epbs) {
354 start >>= epbs;
355 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;
356 ASSERT3U(end, >=, start);
271 txh->txh_space_towrite += (end - start + 1) << max_ibs;
357 txh->txh_space_towrite += (end - start + 1) << max_ibs;
358 if (start != 0) {
359 /*
360 * We also need a new blkid=0 indirect block
361 * to reference any existing file data.
362 */
363 txh->txh_space_towrite += 1ULL << max_ibs;
364 }
272 }
273
365 }
366
274 ASSERT(txh->txh_space_towrite < 2 * DMU_MAX_ACCESS);
275
276out:
367out:
368 if (txh->txh_space_towrite + txh->txh_space_tooverwrite >
369 2 * DMU_MAX_ACCESS)
370 err = EFBIG;
371
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;
372 if (err)
373 txh->txh_tx->tx_err = err;
374}
375
376static void
377dmu_tx_count_dnode(dmu_tx_hold_t *txh)
378{
379 dnode_t *dn = txh->txh_dnode;
380 dnode_t *mdn = txh->txh_tx->tx_objset->os->os_meta_dnode;
381 uint64_t space = mdn->dn_datablksz +
382 ((mdn->dn_nlevels-1) << mdn->dn_indblkshift);
383
384 if (dn && dn->dn_dbuf->db_blkptr &&
385 dsl_dataset_block_freeable(dn->dn_objset->os_dsl_dataset,
386 dn->dn_dbuf->db_blkptr->blk_birth)) {
387 txh->txh_space_tooverwrite += space;
388 txh->txh_space_tounref += 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
389 } else {
390 txh->txh_space_towrite += space;
391 if (dn && dn->dn_dbuf->db_blkptr)
392 txh->txh_space_tounref += space;
393 }
394}
395
396void

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

624 }
625 }
626
627 dmu_tx_count_dnode(txh);
628 dmu_tx_count_free(txh, off, len);
629}
630
631void
536dmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int add, char *name)
632dmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int add, const 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
633{
634 dmu_tx_hold_t *txh;
635 dnode_t *dn;
636 uint64_t nblocks;
637 int epbs, err;
638
639 ASSERT(tx->tx_txg == 0);
640

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

692 err = zap_lookup(&dn->dn_objset->os, dn->dn_object, name,
693 8, 0, NULL);
694 if (err == EIO) {
695 tx->tx_err = err;
696 return;
697 }
698 }
699
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);
700 err = zap_count_write(&dn->dn_objset->os, dn->dn_object, name, add,
701 &txh->txh_space_towrite, &txh->txh_space_tooverwrite);
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)
702
703 /*
704 * If the modified blocks are scattered to the four winds,
705 * we'll have to modify an indirect twig for each.
706 */
707 epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
708 for (nblocks = dn->dn_maxblkid >> epbs; nblocks != 0; nblocks >>= epbs)
617 txh->txh_space_towrite += 3 << dn->dn_indblkshift;
709 if (dn->dn_objset->os_dsl_dataset->ds_phys->ds_prev_snap_obj)
710 txh->txh_space_towrite += 3 << dn->dn_indblkshift;
711 else
712 txh->txh_space_tooverwrite += 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 ---
713}
714
715void
716dmu_tx_hold_bonus(dmu_tx_t *tx, uint64_t object)
717{
718 dmu_tx_hold_t *txh;
719
720 ASSERT(tx->tx_txg == 0);

--- 441 unchanged lines hidden ---