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 --- |