Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Illumos #1862 incremental zfs receive fails for sparse file > 8PB
1862 incremental zfs receive fails for sparse file > 8PB

Reviewed by: Matt Ahrens <matthew.ahrens@delphix.com>
Reviewed by: Simon Klinkert <klinkert@webgods.de>
Approved by: Eric Schrock <eric.schrock@delphix.com>

References:
  illumos/illumos-gate@31495a1
  illumos changeset: 13789:f0c17d471b7a
  https://www.illumos.org/issues/1862

Ported-by: Brian Behlendorf <behlendorf1@llnl.gov>
  • Loading branch information
Arne Jansen authored and behlendorf committed Jan 14, 2013
1 parent a94addd commit ff80d9b
Showing 1 changed file with 27 additions and 15 deletions.
42 changes: 27 additions & 15 deletions module/zfs/dmu_tx.c
Expand Up @@ -446,6 +446,7 @@ dmu_tx_count_free(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset;
spa_t *spa = txh->txh_tx->tx_pool->dp_spa;
int epbs;
uint64_t l0span = 0, nl1blks = 0;

if (dn->dn_nlevels == 0)
return;
Expand Down Expand Up @@ -478,6 +479,7 @@ dmu_tx_count_free(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
nblks = dn->dn_maxblkid - blkid;

}
l0span = nblks; /* save for later use to calc level > 1 overhead */
if (dn->dn_nlevels == 1) {
int i;
for (i = 0; i < nblks; i++) {
Expand All @@ -490,24 +492,10 @@ dmu_tx_count_free(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
}
unref += BP_GET_ASIZE(bp);
}
nl1blks = 1;
nblks = 0;
}

/*
* Add in memory requirements of higher-level indirects.
* This assumes a worst-possible scenario for dn_nlevels.
*/
{
uint64_t blkcnt = 1 + ((nblks >> epbs) >> epbs);
int level = (dn->dn_nlevels > 1) ? 2 : 1;

while (level++ < DN_MAX_LEVELS) {
txh->txh_memory_tohold += blkcnt << dn->dn_indblkshift;
blkcnt = 1 + (blkcnt >> epbs);
}
ASSERT(blkcnt <= dn->dn_nblkptr);
}

lastblk = blkid + nblks - 1;
while (nblks) {
dmu_buf_impl_t *dbuf;
Expand Down Expand Up @@ -578,11 +566,35 @@ dmu_tx_count_free(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
}
dbuf_rele(dbuf, FTAG);

++nl1blks;
blkid += tochk;
nblks -= tochk;
}
rw_exit(&dn->dn_struct_rwlock);

/*
* Add in memory requirements of higher-level indirects.
* This assumes a worst-possible scenario for dn_nlevels and a
* worst-possible distribution of l1-blocks over the region to free.
*/
{
uint64_t blkcnt = 1 + ((l0span >> epbs) >> epbs);
int level = 2;
/*
* Here we don't use DN_MAX_LEVEL, but calculate it with the
* given datablkshift and indblkshift. This makes the
* difference between 19 and 8 on large files.
*/
int maxlevel = 2 + (DN_MAX_OFFSET_SHIFT - dn->dn_datablkshift) /
(dn->dn_indblkshift - SPA_BLKPTRSHIFT);

while (level++ < maxlevel) {
txh->txh_memory_tohold += MIN(blkcnt, (nl1blks >> epbs))
<< dn->dn_indblkshift;
blkcnt = 1 + (blkcnt >> epbs);
}
}

/* account for new level 1 indirect blocks that might show up */
if (skipped > 0) {
txh->txh_fudge += skipped << dn->dn_indblkshift;
Expand Down

0 comments on commit ff80d9b

Please sign in to comment.