Skip to content

Commit ff80d9b

Browse files
Arne Jansenbehlendorf
authored andcommitted
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>
1 parent a94addd commit ff80d9b

File tree

1 file changed

+27
-15
lines changed

1 file changed

+27
-15
lines changed

module/zfs/dmu_tx.c

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ dmu_tx_count_free(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
446446
dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset;
447447
spa_t *spa = txh->txh_tx->tx_pool->dp_spa;
448448
int epbs;
449+
uint64_t l0span = 0, nl1blks = 0;
449450

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

480481
}
482+
l0span = nblks; /* save for later use to calc level > 1 overhead */
481483
if (dn->dn_nlevels == 1) {
482484
int i;
483485
for (i = 0; i < nblks; i++) {
@@ -490,24 +492,10 @@ dmu_tx_count_free(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
490492
}
491493
unref += BP_GET_ASIZE(bp);
492494
}
495+
nl1blks = 1;
493496
nblks = 0;
494497
}
495498

496-
/*
497-
* Add in memory requirements of higher-level indirects.
498-
* This assumes a worst-possible scenario for dn_nlevels.
499-
*/
500-
{
501-
uint64_t blkcnt = 1 + ((nblks >> epbs) >> epbs);
502-
int level = (dn->dn_nlevels > 1) ? 2 : 1;
503-
504-
while (level++ < DN_MAX_LEVELS) {
505-
txh->txh_memory_tohold += blkcnt << dn->dn_indblkshift;
506-
blkcnt = 1 + (blkcnt >> epbs);
507-
}
508-
ASSERT(blkcnt <= dn->dn_nblkptr);
509-
}
510-
511499
lastblk = blkid + nblks - 1;
512500
while (nblks) {
513501
dmu_buf_impl_t *dbuf;
@@ -578,11 +566,35 @@ dmu_tx_count_free(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
578566
}
579567
dbuf_rele(dbuf, FTAG);
580568

569+
++nl1blks;
581570
blkid += tochk;
582571
nblks -= tochk;
583572
}
584573
rw_exit(&dn->dn_struct_rwlock);
585574

575+
/*
576+
* Add in memory requirements of higher-level indirects.
577+
* This assumes a worst-possible scenario for dn_nlevels and a
578+
* worst-possible distribution of l1-blocks over the region to free.
579+
*/
580+
{
581+
uint64_t blkcnt = 1 + ((l0span >> epbs) >> epbs);
582+
int level = 2;
583+
/*
584+
* Here we don't use DN_MAX_LEVEL, but calculate it with the
585+
* given datablkshift and indblkshift. This makes the
586+
* difference between 19 and 8 on large files.
587+
*/
588+
int maxlevel = 2 + (DN_MAX_OFFSET_SHIFT - dn->dn_datablkshift) /
589+
(dn->dn_indblkshift - SPA_BLKPTRSHIFT);
590+
591+
while (level++ < maxlevel) {
592+
txh->txh_memory_tohold += MIN(blkcnt, (nl1blks >> epbs))
593+
<< dn->dn_indblkshift;
594+
blkcnt = 1 + (blkcnt >> epbs);
595+
}
596+
}
597+
586598
/* account for new level 1 indirect blocks that might show up */
587599
if (skipped > 0) {
588600
txh->txh_fudge += skipped << dn->dn_indblkshift;

0 commit comments

Comments
 (0)