Introduce a flag to skip comparing the local mac when raw sending

Raw receiving a snapshot back to the originating dataset is currently
impossible because of user accounting being present in the originating
dataset.

One solution would be resetting user accounting when raw receiving on
the receiving dataset. However, to recalculate it we would have to dirty
all dnodes, which may not be preferable on big datasets.

Instead, we rely on the os_phys flag
OBJSET_FLAG_USERACCOUNTING_COMPLETE to indicate that user accounting is
incomplete when raw receiving. Thus, on the next mount of the receiving
dataset the local mac protecting user accounting is zeroed out.
The flag is then cleared when user accounting of the raw received
snapshot is calculated.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: George Amanakis <gamanakis@gmail.com>
Closes #12981 
Closes #10523
Closes #11221
Closes #11294
Closes #12594
Issue #11300
This commit is contained in:
George Amanakis
2022-01-21 20:41:17 +01:00
committed by GitHub
parent 6e2a59181e
commit 63a26454ba
7 changed files with 163 additions and 14 deletions
+16 -1
View File
@@ -1065,11 +1065,26 @@ zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
bcopy(raw_portable_mac, portable_mac, ZIO_OBJSET_MAC_LEN);
/*
* This is necessary here as we check next whether
* OBJSET_FLAG_USERACCOUNTING_COMPLETE is set in order to
* decide if the local_mac should be zeroed out. That flag will always
* be set by dmu_objset_id_quota_upgrade_cb() and
* dmu_objset_userspace_upgrade_cb() if useraccounting has been
* completed.
*/
intval = osp->os_flags;
if (should_bswap)
intval = BSWAP_64(intval);
boolean_t uacct_incomplete =
!(intval & OBJSET_FLAG_USERACCOUNTING_COMPLETE);
/*
* The local MAC protects the user, group and project accounting.
* If these objects are not present, the local MAC is zeroed out.
*/
if ((datalen >= OBJSET_PHYS_SIZE_V3 &&
if (uacct_incomplete ||
(datalen >= OBJSET_PHYS_SIZE_V3 &&
osp->os_userused_dnode.dn_type == DMU_OT_NONE &&
osp->os_groupused_dnode.dn_type == DMU_OT_NONE &&
osp->os_projectused_dnode.dn_type == DMU_OT_NONE) ||