diff options
author | Tom Caputi <[email protected]> | 2019-06-06 16:47:34 -0400 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-06-06 13:47:33 -0700 |
commit | fd7a657bffccf24a11c60ea63e5dba7aed635961 (patch) | |
tree | 8157a0b8bf61558727835b147a1f2a67e85cb647 /module | |
parent | b7109a413c4724e05f535876f8902c26804ab3ce (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')
-rw-r--r-- | module/zfs/dnode_sync.c | 16 |
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; |