Print this page
4082 zfs receive gets EFBIG from dmu_tx_hold_free()
Reviewed by: Eric Schrock <eric.schrock@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>


 588 {
 589         dmu_tx_hold_t *txh;
 590         dnode_t *dn;
 591         int err;
 592         zio_t *zio;
 593 
 594         ASSERT(tx->tx_txg == 0);
 595 
 596         txh = dmu_tx_hold_object_impl(tx, tx->tx_objset,
 597             object, THT_FREE, off, len);
 598         if (txh == NULL)
 599                 return;
 600         dn = txh->txh_dnode;
 601         dmu_tx_count_dnode(txh);
 602 
 603         if (off >= (dn->dn_maxblkid+1) * dn->dn_datablksz)
 604                 return;
 605         if (len == DMU_OBJECT_END)
 606                 len = (dn->dn_maxblkid+1) * dn->dn_datablksz - off;
 607 
 608 
 609         /*
 610          * For i/o error checking, we read the first and last level-0
 611          * blocks if they are not aligned, and all the level-1 blocks.
 612          *
 613          * Note:  dbuf_free_range() assumes that we have not instantiated
 614          * any level-0 dbufs that will be completely freed.  Therefore we must
 615          * exercise care to not read or count the first and last blocks
 616          * if they are blocksize-aligned.
 617          */
 618         if (dn->dn_datablkshift == 0) {
 619                 if (off != 0 || len < dn->dn_datablksz)
 620                         dmu_tx_count_write(txh, off, len);
 621         } else {
 622                 /* first block will be modified if it is not aligned */
 623                 if (!IS_P2ALIGNED(off, 1 << dn->dn_datablkshift))
 624                         dmu_tx_count_write(txh, off, 1);
 625                 /* last block will be modified if it is not aligned */
 626                 if (!IS_P2ALIGNED(off + len, 1 << dn->dn_datablkshift))
 627                         dmu_tx_count_write(txh, off+len, 1);
 628         }
 629 
 630         /*
 631          * Check level-1 blocks.
 632          */
 633         if (dn->dn_nlevels > 1) {
 634                 int shift = dn->dn_datablkshift + dn->dn_indblkshift -
 635                     SPA_BLKPTRSHIFT;
 636                 uint64_t start = off >> shift;
 637                 uint64_t end = (off + len) >> shift;
 638 
 639                 ASSERT(dn->dn_datablkshift != 0);
 640                 ASSERT(dn->dn_indblkshift != 0);




 588 {
 589         dmu_tx_hold_t *txh;
 590         dnode_t *dn;
 591         int err;
 592         zio_t *zio;
 593 
 594         ASSERT(tx->tx_txg == 0);
 595 
 596         txh = dmu_tx_hold_object_impl(tx, tx->tx_objset,
 597             object, THT_FREE, off, len);
 598         if (txh == NULL)
 599                 return;
 600         dn = txh->txh_dnode;
 601         dmu_tx_count_dnode(txh);
 602 
 603         if (off >= (dn->dn_maxblkid+1) * dn->dn_datablksz)
 604                 return;
 605         if (len == DMU_OBJECT_END)
 606                 len = (dn->dn_maxblkid+1) * dn->dn_datablksz - off;
 607 

 608         /*
 609          * For i/o error checking, we read the first and last level-0
 610          * blocks if they are not aligned, and all the level-1 blocks.
 611          *
 612          * Note:  dbuf_free_range() assumes that we have not instantiated
 613          * any level-0 dbufs that will be completely freed.  Therefore we must
 614          * exercise care to not read or count the first and last blocks
 615          * if they are blocksize-aligned.
 616          */
 617         if (dn->dn_datablkshift == 0) {
 618                 if (off != 0 || len < dn->dn_datablksz)
 619                         dmu_tx_count_write(txh, 0, dn->dn_datablksz);
 620         } else {
 621                 /* first block will be modified if it is not aligned */
 622                 if (!IS_P2ALIGNED(off, 1 << dn->dn_datablkshift))
 623                         dmu_tx_count_write(txh, off, 1);
 624                 /* last block will be modified if it is not aligned */
 625                 if (!IS_P2ALIGNED(off + len, 1 << dn->dn_datablkshift))
 626                         dmu_tx_count_write(txh, off+len, 1);
 627         }
 628 
 629         /*
 630          * Check level-1 blocks.
 631          */
 632         if (dn->dn_nlevels > 1) {
 633                 int shift = dn->dn_datablkshift + dn->dn_indblkshift -
 634                     SPA_BLKPTRSHIFT;
 635                 uint64_t start = off >> shift;
 636                 uint64_t end = (off + len) >> shift;
 637 
 638                 ASSERT(dn->dn_datablkshift != 0);
 639                 ASSERT(dn->dn_indblkshift != 0);