summaryrefslogtreecommitdiffstats
path: root/module/zfs/dnode_sync.c
diff options
context:
space:
mode:
authorTom Caputi <[email protected]>2019-03-13 13:52:01 -0400
committerBrian Behlendorf <[email protected]>2019-03-13 10:52:01 -0700
commit369aa501d11f4d21d4732b58d749259ad811a10a (patch)
tree747a00e61b8ae4348cccaa0cd234b39383898f57 /module/zfs/dnode_sync.c
parent146bdc414c7ad5b93417569bff6737d57860ff14 (diff)
Fix handling of maxblkid for raw sends
Currently, the receive code can create an unreadable dataset from a correct raw send stream. This is because it is currently impossible to set maxblkid to a lower value without freeing the associated object. This means truncating files on the send side to a non-0 size could result in corruption. This patch solves this issue by adding a new 'force' flag to dnode_new_blkid() which will allow the raw receive code to force the DMU to accept the provided maxblkid even if it is a lower value than the existing one. For testing purposes the send_encrypted_files.ksh test has been extended to include a variety of truncated files and multiple snapshots. It also now leverages the xattrtest command to help ensure raw receives correctly handle xattrs. Reviewed-by: Paul Dagnelie <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Matt Ahrens <[email protected]> Signed-off-by: Tom Caputi <[email protected]> Closes #8168 Closes #8487
Diffstat (limited to 'module/zfs/dnode_sync.c')
-rw-r--r--module/zfs/dnode_sync.c13
1 files changed, 5 insertions, 8 deletions
diff --git a/module/zfs/dnode_sync.c b/module/zfs/dnode_sync.c
index c4062beb3..581f812a1 100644
--- a/module/zfs/dnode_sync.c
+++ b/module/zfs/dnode_sync.c
@@ -384,12 +384,7 @@ dnode_sync_free_range_impl(dnode_t *dn, uint64_t blkid, uint64_t nblks,
}
}
- /*
- * Do not truncate the maxblkid if we are performing a raw
- * receive. The raw receive sets the mablkid manually and
- * must not be overriden.
- */
- if (trunc && !dn->dn_objset->os_raw_receive) {
+ if (trunc) {
ASSERTV(uint64_t off);
dn->dn_phys->dn_maxblkid = blkid == 0 ? 0 : blkid - 1;
@@ -765,11 +760,13 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
/*
* This must be done after dnode_sync_free_range()
- * and dnode_increase_indirection().
+ * and dnode_increase_indirection(). See dnode_new_blkid()
+ * for an explanation of the high bit being set.
*/
if (dn->dn_next_maxblkid[txgoff]) {
mutex_enter(&dn->dn_mtx);
- dnp->dn_maxblkid = dn->dn_next_maxblkid[txgoff];
+ dnp->dn_maxblkid =
+ dn->dn_next_maxblkid[txgoff] & ~DMU_NEXT_MAXBLKID_SET;
dn->dn_next_maxblkid[txgoff] = 0;
mutex_exit(&dn->dn_mtx);
}