summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c
diff options
context:
space:
mode:
authormm <mm@FreeBSD.org>2012-09-05 12:02:09 +0000
committermm <mm@FreeBSD.org>2012-09-05 12:02:09 +0000
commit3a59a28395e506fbec113160179d4c50fe9b3c25 (patch)
tree9cb7bfc2b298035a5e16527a5e95add3afffa44a /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c
parentdfb185f5592710a31d133dc2ce652110587f6c1e (diff)
downloadFreeBSD-src-3a59a28395e506fbec113160179d4c50fe9b3c25.zip
FreeBSD-src-3a59a28395e506fbec113160179d4c50fe9b3c25.tar.gz
Merge recent vendor changes and sync code:
1862 incremental zfs receive fails for sparse file > 8PB 3112 ztest does not honor ZFS_DEBUG 3122 zfs destroy filesystem should prefetch blocks 3129 'zpool reopen' restarts resilvers 3130 ztest failure: Assertion failed: 0 == dmu_objset_destroy(name, B_FALSE) (0x0 == 0x10) References: https://www.illumos.org/issues/1862 https://www.illumos.org/issues/3112 https://www.illumos.org/issues/3122 https://www.illumos.org/issues/3129 https://www.illumos.org/issues/3130 Obtained from: illumos (vendor/illumos, vendor/illumos-sys) MFC after: 2 weeks
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c
index 3dd5f2c..f9d7397 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c
@@ -429,6 +429,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;
@@ -461,6 +462,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++) {
@@ -473,24 +475,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;
@@ -561,11 +549,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;
OpenPOWER on IntegriCloud