mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 10:54:35 +03:00
Allow block cloning across encrypted datasets
When two datasets share the same master encryption key, it is safe to clone encrypted blocks. Currently only snapshots and clones of a dataset share with it the same encryption key. Added a test for: - Clone from encrypted sibling to encrypted sibling with non encrypted parent - Clone from encrypted parent to inherited encrypted child - Clone from child to sibling with encrypted parent - Clone from snapshot to the original datasets - Clone from foreign snapshot to a foreign dataset - Cloning from non-encrypted to encrypted datasets - Cloning from encrypted to non-encrypted datasets Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Original-patch-by: Pawel Jakub Dawidek <pawel@dawidek.net> Signed-off-by: Kay Pedersen <mail@mkwg.de> Closes #15544
This commit is contained in:
+2
-4
@@ -157,10 +157,8 @@
|
||||
* (copying the file content to the new dataset and removing the source file).
|
||||
* In that case Block Cloning will only be used briefly, because the BRT entries
|
||||
* will be removed when the source is removed.
|
||||
* Note: currently it is not possible to clone blocks between encrypted
|
||||
* datasets, even if those datasets use the same encryption key (this includes
|
||||
* snapshots of encrypted datasets). Cloning blocks between datasets that use
|
||||
* the same keys should be possible and should be implemented in the future.
|
||||
* Block Cloning across encrypted datasets is supported as long as both
|
||||
* datasets share the same master key (e.g. snapshots and clones)
|
||||
*
|
||||
* Block Cloning flow through ZFS layers.
|
||||
*
|
||||
|
||||
@@ -266,6 +266,40 @@ spa_crypto_key_compare(const void *a, const void *b)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* this compares a crypto key based on zk_guid. See comment on
|
||||
* spa_crypto_key_compare for more information.
|
||||
*/
|
||||
boolean_t
|
||||
dmu_objset_crypto_key_equal(objset_t *osa, objset_t *osb)
|
||||
{
|
||||
dsl_crypto_key_t *dcka = NULL;
|
||||
dsl_crypto_key_t *dckb = NULL;
|
||||
uint64_t obja, objb;
|
||||
boolean_t equal;
|
||||
spa_t *spa;
|
||||
|
||||
spa = dmu_objset_spa(osa);
|
||||
if (spa != dmu_objset_spa(osb))
|
||||
return (B_FALSE);
|
||||
obja = dmu_objset_ds(osa)->ds_object;
|
||||
objb = dmu_objset_ds(osb)->ds_object;
|
||||
|
||||
if (spa_keystore_lookup_key(spa, obja, FTAG, &dcka) != 0)
|
||||
return (B_FALSE);
|
||||
if (spa_keystore_lookup_key(spa, objb, FTAG, &dckb) != 0) {
|
||||
spa_keystore_dsl_key_rele(spa, dcka, FTAG);
|
||||
return (B_FALSE);
|
||||
}
|
||||
|
||||
equal = (dcka->dck_key.zk_guid == dckb->dck_key.zk_guid);
|
||||
|
||||
spa_keystore_dsl_key_rele(spa, dcka, FTAG);
|
||||
spa_keystore_dsl_key_rele(spa, dckb, FTAG);
|
||||
|
||||
return (equal);
|
||||
}
|
||||
|
||||
static int
|
||||
spa_key_mapping_compare(const void *a, const void *b)
|
||||
{
|
||||
|
||||
+11
-14
@@ -47,6 +47,7 @@
|
||||
#include <sys/fs/zfs.h>
|
||||
#include <sys/dmu.h>
|
||||
#include <sys/dmu_objset.h>
|
||||
#include <sys/dsl_crypt.h>
|
||||
#include <sys/spa.h>
|
||||
#include <sys/txg.h>
|
||||
#include <sys/dbuf.h>
|
||||
@@ -1097,6 +1098,16 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp,
|
||||
return (SET_ERROR(EXDEV));
|
||||
}
|
||||
|
||||
/*
|
||||
* Cloning across encrypted datasets is possible only if they
|
||||
* share the same master key.
|
||||
*/
|
||||
if (inos != outos && inos->os_encrypted &&
|
||||
!dmu_objset_crypto_key_equal(inos, outos)) {
|
||||
zfs_exit_two(inzfsvfs, outzfsvfs, FTAG);
|
||||
return (SET_ERROR(EXDEV));
|
||||
}
|
||||
|
||||
error = zfs_verify_zp(inzp);
|
||||
if (error == 0)
|
||||
error = zfs_verify_zp(outzp);
|
||||
@@ -1280,20 +1291,6 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp,
|
||||
*/
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Encrypted data is fine as long as it comes from the same
|
||||
* dataset.
|
||||
* TODO: We want to extend it in the future to allow cloning to
|
||||
* datasets with the same keys, like clones or to be able to
|
||||
* clone a file from a snapshot of an encrypted dataset into the
|
||||
* dataset itself.
|
||||
*/
|
||||
if (BP_IS_PROTECTED(&bps[0])) {
|
||||
if (inzfsvfs != outzfsvfs) {
|
||||
error = SET_ERROR(EXDEV);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Start a transaction.
|
||||
|
||||
Reference in New Issue
Block a user