summaryrefslogtreecommitdiffstats
path: root/module/zfs/dnode_sync.c
diff options
context:
space:
mode:
authorTom Caputi <[email protected]>2019-06-06 16:47:34 -0400
committerBrian Behlendorf <[email protected]>2019-06-06 13:47:33 -0700
commitfd7a657bffccf24a11c60ea63e5dba7aed635961 (patch)
tree8157a0b8bf61558727835b147a1f2a67e85cb647 /module/zfs/dnode_sync.c
parentb7109a413c4724e05f535876f8902c26804ab3ce (diff)
Reinstate raw receive check when truncating
This patch re-adds a check that was removed in 369aa50. The check confirms that a raw receive is not occuring before truncating an object's dn_maxblkid. At the time, it was believed that all cases that would hit this code path would be handled in other places, but that was not the case. Reviewed-by: Matt Ahrens <[email protected]> Reviewed-by: Paul Dagnelie <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Tom Caputi <[email protected]> Closes #8852 Closes #8857
Diffstat (limited to 'module/zfs/dnode_sync.c')
-rw-r--r--module/zfs/dnode_sync.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/module/zfs/dnode_sync.c b/module/zfs/dnode_sync.c
index 581f812a1..d3acf1baa 100644
--- a/module/zfs/dnode_sync.c
+++ b/module/zfs/dnode_sync.c
@@ -384,7 +384,21 @@ dnode_sync_free_range_impl(dnode_t *dn, uint64_t blkid, uint64_t nblks,
}
}
- if (trunc) {
+ /*
+ * Do not truncate the maxblkid if we are performing a raw
+ * receive. The raw receive sets the maxblkid manually and
+ * must not be overridden. Usually, the last DRR_FREE record
+ * will be at the maxblkid, because the source system sets
+ * the maxblkid when truncating. However, if the last block
+ * was freed by overwriting with zeros and being compressed
+ * away to a hole, the source system will generate a DRR_FREE
+ * record while leaving the maxblkid after the end of that
+ * record. In this case we need to leave the maxblkid as
+ * indicated in the DRR_OBJECT record, so that it matches the
+ * source system, ensuring that the cryptographic hashes will
+ * match.
+ */
+ if (trunc && !dn->dn_objset->os_raw_receive) {
ASSERTV(uint64_t off);
dn->dn_phys->dn_maxblkid = blkid == 0 ? 0 : blkid - 1;