mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2025-01-13 19:50:25 +03:00
Send / Recv Fixes following b52563
This patch fixes several issues discovered after the encryption patch was merged: * Fixed a bug where encrypted datasets could attempt to receive embedded data records. * Fixed a bug where dirty records created by the recv code wasn't properly setting the dr_raw flag. * Fixed a typo where a dmu_tx_commit() was changed to dmu_tx_abort() * Fixed a few error handling bugs unrelated to the encryption patch in dmu_recv_stream() Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Tom Caputi <tcaputi@datto.com> Closes #6512 Closes #6524 Closes #6545
This commit is contained in:
parent
db4c1adaf8
commit
9b8407638d
@ -448,8 +448,9 @@ void dmu_object_set_checksum(objset_t *os, uint64_t object, uint8_t checksum,
|
|||||||
void dmu_object_set_compress(objset_t *os, uint64_t object, uint8_t compress,
|
void dmu_object_set_compress(objset_t *os, uint64_t object, uint8_t compress,
|
||||||
dmu_tx_t *tx);
|
dmu_tx_t *tx);
|
||||||
|
|
||||||
void
|
int dmu_object_dirty_raw(objset_t *os, uint64_t object, dmu_tx_t *tx);
|
||||||
dmu_write_embedded(objset_t *os, uint64_t object, uint64_t offset,
|
|
||||||
|
void dmu_write_embedded(objset_t *os, uint64_t object, uint64_t offset,
|
||||||
void *data, uint8_t etype, uint8_t comp, int uncompressed_size,
|
void *data, uint8_t etype, uint8_t comp, int uncompressed_size,
|
||||||
int compressed_size, int byteorder, dmu_tx_t *tx);
|
int compressed_size, int byteorder, dmu_tx_t *tx);
|
||||||
|
|
||||||
|
@ -164,11 +164,9 @@ typedef enum dmu_send_resume_token_version {
|
|||||||
* DRR_WRITE_BYREF, and DRR_OBJECT_RANGE blocks
|
* DRR_WRITE_BYREF, and DRR_OBJECT_RANGE blocks
|
||||||
*/
|
*/
|
||||||
#define DRR_CHECKSUM_DEDUP (1<<0) /* not used for DRR_SPILL blocks */
|
#define DRR_CHECKSUM_DEDUP (1<<0) /* not used for DRR_SPILL blocks */
|
||||||
#define DRR_RAW_ENCRYPTED (1<<1)
|
#define DRR_RAW_BYTESWAP (1<<1)
|
||||||
#define DRR_RAW_BYTESWAP (1<<2)
|
|
||||||
|
|
||||||
#define DRR_IS_DEDUP_CAPABLE(flags) ((flags) & DRR_CHECKSUM_DEDUP)
|
#define DRR_IS_DEDUP_CAPABLE(flags) ((flags) & DRR_CHECKSUM_DEDUP)
|
||||||
#define DRR_IS_RAW_ENCRYPTED(flags) ((flags) & DRR_RAW_ENCRYPTED)
|
|
||||||
#define DRR_IS_RAW_BYTESWAPPED(flags) ((flags) & DRR_RAW_BYTESWAP)
|
#define DRR_IS_RAW_BYTESWAPPED(flags) ((flags) & DRR_RAW_BYTESWAP)
|
||||||
|
|
||||||
/* deal with compressed drr_write replay records */
|
/* deal with compressed drr_write replay records */
|
||||||
@ -177,11 +175,11 @@ typedef enum dmu_send_resume_token_version {
|
|||||||
(DRR_WRITE_COMPRESSED(drrw) ? (drrw)->drr_compressed_size : \
|
(DRR_WRITE_COMPRESSED(drrw) ? (drrw)->drr_compressed_size : \
|
||||||
(drrw)->drr_logical_size)
|
(drrw)->drr_logical_size)
|
||||||
#define DRR_SPILL_PAYLOAD_SIZE(drrs) \
|
#define DRR_SPILL_PAYLOAD_SIZE(drrs) \
|
||||||
(DRR_IS_RAW_ENCRYPTED(drrs->drr_flags) ? \
|
((drrs)->drr_compressed_size ? \
|
||||||
(drrs)->drr_compressed_size : (drrs)->drr_length)
|
(drrs)->drr_compressed_size : (drrs)->drr_length)
|
||||||
#define DRR_OBJECT_PAYLOAD_SIZE(drro) \
|
#define DRR_OBJECT_PAYLOAD_SIZE(drro) \
|
||||||
(DRR_IS_RAW_ENCRYPTED(drro->drr_flags) ? \
|
((drro)->drr_raw_bonuslen != 0 ? \
|
||||||
drro->drr_raw_bonuslen : P2ROUNDUP(drro->drr_bonuslen, 8))
|
(drro)->drr_raw_bonuslen : P2ROUNDUP((drro)->drr_bonuslen, 8))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* zfs ioctl command structure
|
* zfs ioctl command structure
|
||||||
@ -221,7 +219,7 @@ typedef struct dmu_replay_record {
|
|||||||
uint8_t drr_flags;
|
uint8_t drr_flags;
|
||||||
uint32_t drr_raw_bonuslen;
|
uint32_t drr_raw_bonuslen;
|
||||||
uint64_t drr_toguid;
|
uint64_t drr_toguid;
|
||||||
/* only nonzero if DRR_RAW_ENCRYPTED flag is set */
|
/* only nonzero for raw streams */
|
||||||
uint8_t drr_indblkshift;
|
uint8_t drr_indblkshift;
|
||||||
uint8_t drr_nlevels;
|
uint8_t drr_nlevels;
|
||||||
uint8_t drr_nblkptr;
|
uint8_t drr_nblkptr;
|
||||||
@ -247,7 +245,7 @@ typedef struct dmu_replay_record {
|
|||||||
ddt_key_t drr_key;
|
ddt_key_t drr_key;
|
||||||
/* only nonzero if drr_compressiontype is not 0 */
|
/* only nonzero if drr_compressiontype is not 0 */
|
||||||
uint64_t drr_compressed_size;
|
uint64_t drr_compressed_size;
|
||||||
/* only nonzero if DRR_RAW_ENCRYPTED flag is set */
|
/* only nonzero for raw streams */
|
||||||
uint8_t drr_salt[ZIO_DATA_SALT_LEN];
|
uint8_t drr_salt[ZIO_DATA_SALT_LEN];
|
||||||
uint8_t drr_iv[ZIO_DATA_IV_LEN];
|
uint8_t drr_iv[ZIO_DATA_IV_LEN];
|
||||||
uint8_t drr_mac[ZIO_DATA_MAC_LEN];
|
uint8_t drr_mac[ZIO_DATA_MAC_LEN];
|
||||||
@ -282,7 +280,7 @@ typedef struct dmu_replay_record {
|
|||||||
uint8_t drr_flags;
|
uint8_t drr_flags;
|
||||||
uint8_t drr_compressiontype;
|
uint8_t drr_compressiontype;
|
||||||
uint8_t drr_pad[6];
|
uint8_t drr_pad[6];
|
||||||
/* only nonzero if DRR_RAW_ENCRYPTED flag is set */
|
/* only nonzero for raw streams */
|
||||||
uint64_t drr_compressed_size;
|
uint64_t drr_compressed_size;
|
||||||
uint8_t drr_salt[ZIO_DATA_SALT_LEN];
|
uint8_t drr_salt[ZIO_DATA_SALT_LEN];
|
||||||
uint8_t drr_iv[ZIO_DATA_IV_LEN];
|
uint8_t drr_iv[ZIO_DATA_IV_LEN];
|
||||||
|
@ -3735,6 +3735,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
|||||||
DMU_BACKUP_FEATURE_RESUMING;
|
DMU_BACKUP_FEATURE_RESUMING;
|
||||||
boolean_t raw = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
|
boolean_t raw = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
|
||||||
DMU_BACKUP_FEATURE_RAW;
|
DMU_BACKUP_FEATURE_RAW;
|
||||||
|
boolean_t embedded = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
|
||||||
|
DMU_BACKUP_FEATURE_EMBED_DATA;
|
||||||
stream_wantsnewfs = (drrb->drr_fromguid == 0 ||
|
stream_wantsnewfs = (drrb->drr_fromguid == 0 ||
|
||||||
(drrb->drr_flags & DRR_FLAG_CLONE) || originsnap) && !resuming;
|
(drrb->drr_flags & DRR_FLAG_CLONE) || originsnap) && !resuming;
|
||||||
|
|
||||||
@ -4132,6 +4134,10 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
|||||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||||
"kernel modules must be upgraded to "
|
"kernel modules must be upgraded to "
|
||||||
"receive this stream."));
|
"receive this stream."));
|
||||||
|
if (embedded && !raw)
|
||||||
|
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||||
|
"incompatible embedded data stream "
|
||||||
|
"feature with encrypted receive."));
|
||||||
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
|
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
|
||||||
break;
|
break;
|
||||||
case ECKSUM:
|
case ECKSUM:
|
||||||
|
@ -3338,7 +3338,8 @@ feature enabled.
|
|||||||
If the
|
If the
|
||||||
.Sy lz4_compress
|
.Sy lz4_compress
|
||||||
feature is active on the sending system, then the receiving system must have
|
feature is active on the sending system, then the receiving system must have
|
||||||
that feature enabled as well.
|
that feature enabled as well. Note that streams generated using this flag are
|
||||||
|
unable to be received into an encrypted dataset.
|
||||||
See
|
See
|
||||||
.Xr zpool-features 5
|
.Xr zpool-features 5
|
||||||
for details on ZFS feature flags and the
|
for details on ZFS feature flags and the
|
||||||
|
@ -2016,6 +2016,25 @@ dmu_object_set_compress(objset_t *os, uint64_t object, uint8_t compress,
|
|||||||
dnode_rele(dn, FTAG);
|
dnode_rele(dn, FTAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dirty an object and set the dirty record's raw flag. This is used
|
||||||
|
* when writing raw data to an object that will not effect the
|
||||||
|
* encryption parameters, specifically during raw receives.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
dmu_object_dirty_raw(objset_t *os, uint64_t object, dmu_tx_t *tx)
|
||||||
|
{
|
||||||
|
dnode_t *dn;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = dnode_hold(os, object, FTAG, &dn);
|
||||||
|
if (err)
|
||||||
|
return (err);
|
||||||
|
dmu_buf_will_change_crypt_params((dmu_buf_t *)dn->dn_dbuf, tx);
|
||||||
|
dnode_rele(dn, FTAG);
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
|
||||||
int zfs_mdcomp_disable = 0;
|
int zfs_mdcomp_disable = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -327,12 +327,11 @@ dump_write(dmu_sendarg_t *dsp, dmu_object_type_t type, uint64_t object,
|
|||||||
ASSERT(BP_IS_PROTECTED(bp));
|
ASSERT(BP_IS_PROTECTED(bp));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a raw protected block so we set the encrypted
|
* This is a raw protected block so we need to pass
|
||||||
* flag. We need to pass along everything the receiving
|
* along everything the receiving side will need to
|
||||||
* side will need to interpret this block, including the
|
* interpret this block, including the byteswap, salt,
|
||||||
* byteswap, salt, IV, and MAC.
|
* IV, and MAC.
|
||||||
*/
|
*/
|
||||||
drrw->drr_flags |= DRR_RAW_ENCRYPTED;
|
|
||||||
if (BP_SHOULD_BYTESWAP(bp))
|
if (BP_SHOULD_BYTESWAP(bp))
|
||||||
drrw->drr_flags |= DRR_RAW_BYTESWAP;
|
drrw->drr_flags |= DRR_RAW_BYTESWAP;
|
||||||
zio_crypt_decode_params_bp(bp, drrw->drr_salt,
|
zio_crypt_decode_params_bp(bp, drrw->drr_salt,
|
||||||
@ -435,9 +434,9 @@ dump_spill(dmu_sendarg_t *dsp, const blkptr_t *bp, uint64_t object, void *data)
|
|||||||
drrs->drr_toguid = dsp->dsa_toguid;
|
drrs->drr_toguid = dsp->dsa_toguid;
|
||||||
|
|
||||||
/* handle raw send fields */
|
/* handle raw send fields */
|
||||||
if ((dsp->dsa_featureflags & DMU_BACKUP_FEATURE_RAW) != 0 &&
|
if (dsp->dsa_featureflags & DMU_BACKUP_FEATURE_RAW) {
|
||||||
BP_IS_PROTECTED(bp)) {
|
ASSERT(BP_IS_PROTECTED(bp));
|
||||||
drrs->drr_flags |= DRR_RAW_ENCRYPTED;
|
|
||||||
if (BP_SHOULD_BYTESWAP(bp))
|
if (BP_SHOULD_BYTESWAP(bp))
|
||||||
drrs->drr_flags |= DRR_RAW_BYTESWAP;
|
drrs->drr_flags |= DRR_RAW_BYTESWAP;
|
||||||
drrs->drr_compressiontype = BP_GET_COMPRESS(bp);
|
drrs->drr_compressiontype = BP_GET_COMPRESS(bp);
|
||||||
@ -543,9 +542,9 @@ dump_dnode(dmu_sendarg_t *dsp, const blkptr_t *bp, uint64_t object,
|
|||||||
drro->drr_blksz > SPA_OLD_MAXBLOCKSIZE)
|
drro->drr_blksz > SPA_OLD_MAXBLOCKSIZE)
|
||||||
drro->drr_blksz = SPA_OLD_MAXBLOCKSIZE;
|
drro->drr_blksz = SPA_OLD_MAXBLOCKSIZE;
|
||||||
|
|
||||||
if ((dsp->dsa_featureflags & DMU_BACKUP_FEATURE_RAW) &&
|
if ((dsp->dsa_featureflags & DMU_BACKUP_FEATURE_RAW)) {
|
||||||
BP_IS_PROTECTED(bp)) {
|
ASSERT(BP_IS_ENCRYPTED(bp));
|
||||||
drro->drr_flags |= DRR_RAW_ENCRYPTED;
|
|
||||||
if (BP_SHOULD_BYTESWAP(bp))
|
if (BP_SHOULD_BYTESWAP(bp))
|
||||||
drro->drr_flags |= DRR_RAW_BYTESWAP;
|
drro->drr_flags |= DRR_RAW_BYTESWAP;
|
||||||
|
|
||||||
@ -602,7 +601,6 @@ dump_object_range(dmu_sendarg_t *dsp, const blkptr_t *bp, uint64_t firstobj,
|
|||||||
drror->drr_firstobj = firstobj;
|
drror->drr_firstobj = firstobj;
|
||||||
drror->drr_numslots = numslots;
|
drror->drr_numslots = numslots;
|
||||||
drror->drr_toguid = dsp->dsa_toguid;
|
drror->drr_toguid = dsp->dsa_toguid;
|
||||||
drror->drr_flags |= DRR_RAW_ENCRYPTED;
|
|
||||||
if (BP_SHOULD_BYTESWAP(bp))
|
if (BP_SHOULD_BYTESWAP(bp))
|
||||||
drror->drr_flags |= DRR_RAW_BYTESWAP;
|
drror->drr_flags |= DRR_RAW_BYTESWAP;
|
||||||
zio_crypt_decode_params_bp(bp, drror->drr_salt, drror->drr_iv);
|
zio_crypt_decode_params_bp(bp, drror->drr_salt, drror->drr_iv);
|
||||||
@ -1725,15 +1723,13 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
if (!origin->ds_is_snapshot) {
|
if (!origin->ds_is_snapshot) {
|
||||||
dsl_dataset_rele_flags(origin,
|
dsl_dataset_rele_flags(origin, dsflags, FTAG);
|
||||||
DS_HOLD_FLAG_DECRYPT, FTAG);
|
|
||||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||||
return (SET_ERROR(EINVAL));
|
return (SET_ERROR(EINVAL));
|
||||||
}
|
}
|
||||||
if (dsl_dataset_phys(origin)->ds_guid != fromguid &&
|
if (dsl_dataset_phys(origin)->ds_guid != fromguid &&
|
||||||
fromguid != 0) {
|
fromguid != 0) {
|
||||||
dsl_dataset_rele_flags(origin,
|
dsl_dataset_rele_flags(origin, dsflags, FTAG);
|
||||||
DS_HOLD_FLAG_DECRYPT, FTAG);
|
|
||||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||||
return (SET_ERROR(ENODEV));
|
return (SET_ERROR(ENODEV));
|
||||||
}
|
}
|
||||||
@ -2136,6 +2132,7 @@ struct receive_writer_arg {
|
|||||||
/* A map from guid to dataset to help handle dedup'd streams. */
|
/* A map from guid to dataset to help handle dedup'd streams. */
|
||||||
avl_tree_t *guid_to_ds_map;
|
avl_tree_t *guid_to_ds_map;
|
||||||
boolean_t resumable;
|
boolean_t resumable;
|
||||||
|
boolean_t raw;
|
||||||
uint64_t last_object, last_offset;
|
uint64_t last_object, last_offset;
|
||||||
uint64_t bytes_read; /* bytes read when current record created */
|
uint64_t bytes_read; /* bytes read when current record created */
|
||||||
};
|
};
|
||||||
@ -2170,6 +2167,7 @@ struct receive_arg {
|
|||||||
zio_cksum_t prev_cksum;
|
zio_cksum_t prev_cksum;
|
||||||
int err;
|
int err;
|
||||||
boolean_t byteswap;
|
boolean_t byteswap;
|
||||||
|
boolean_t raw;
|
||||||
uint64_t featureflags;
|
uint64_t featureflags;
|
||||||
/* Sorted list of objects not to issue prefetches for. */
|
/* Sorted list of objects not to issue prefetches for. */
|
||||||
struct objlist ignore_objlist;
|
struct objlist ignore_objlist;
|
||||||
@ -2416,7 +2414,7 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
|
|||||||
return (SET_ERROR(EINVAL));
|
return (SET_ERROR(EINVAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DRR_IS_RAW_ENCRYPTED(drro->drr_flags)) {
|
if (rwa->raw) {
|
||||||
if (drro->drr_raw_bonuslen < drro->drr_bonuslen ||
|
if (drro->drr_raw_bonuslen < drro->drr_bonuslen ||
|
||||||
drro->drr_indblkshift > SPA_MAXBLOCKSHIFT ||
|
drro->drr_indblkshift > SPA_MAXBLOCKSHIFT ||
|
||||||
drro->drr_nlevels > DN_MAX_LEVELS ||
|
drro->drr_nlevels > DN_MAX_LEVELS ||
|
||||||
@ -2451,13 +2449,12 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
|
|||||||
drro->drr_bonuslen);
|
drro->drr_bonuslen);
|
||||||
|
|
||||||
/* nblkptr will be bounded by the bonus size and type */
|
/* nblkptr will be bounded by the bonus size and type */
|
||||||
if (DRR_IS_RAW_ENCRYPTED(drro->drr_flags) &&
|
if (rwa->raw && nblkptr != drro->drr_nblkptr)
|
||||||
nblkptr != drro->drr_nblkptr)
|
|
||||||
return (SET_ERROR(EINVAL));
|
return (SET_ERROR(EINVAL));
|
||||||
|
|
||||||
if (drro->drr_blksz != doi.doi_data_block_size ||
|
if (drro->drr_blksz != doi.doi_data_block_size ||
|
||||||
nblkptr < doi.doi_nblkptr ||
|
nblkptr < doi.doi_nblkptr ||
|
||||||
(DRR_IS_RAW_ENCRYPTED(drro->drr_flags) &&
|
(rwa->raw &&
|
||||||
(indblksz != doi.doi_metadata_block_size ||
|
(indblksz != doi.doi_metadata_block_size ||
|
||||||
drro->drr_nlevels < doi.doi_indirection))) {
|
drro->drr_nlevels < doi.doi_indirection))) {
|
||||||
err = dmu_free_long_range(rwa->os, drro->drr_object,
|
err = dmu_free_long_range(rwa->os, drro->drr_object,
|
||||||
@ -2492,17 +2489,20 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
|
|||||||
drro->drr_bonustype, drro->drr_bonuslen, tx);
|
drro->drr_bonustype, drro->drr_bonuslen, tx);
|
||||||
}
|
}
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
dmu_tx_abort(tx);
|
dmu_tx_commit(tx);
|
||||||
return (SET_ERROR(EINVAL));
|
return (SET_ERROR(EINVAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rwa->raw)
|
||||||
|
VERIFY0(dmu_object_dirty_raw(rwa->os, drro->drr_object, tx));
|
||||||
|
|
||||||
dmu_object_set_checksum(rwa->os, drro->drr_object,
|
dmu_object_set_checksum(rwa->os, drro->drr_object,
|
||||||
drro->drr_checksumtype, tx);
|
drro->drr_checksumtype, tx);
|
||||||
dmu_object_set_compress(rwa->os, drro->drr_object,
|
dmu_object_set_compress(rwa->os, drro->drr_object,
|
||||||
drro->drr_compress, tx);
|
drro->drr_compress, tx);
|
||||||
|
|
||||||
/* handle more restrictive dnode structuring for raw recvs */
|
/* handle more restrictive dnode structuring for raw recvs */
|
||||||
if (DRR_IS_RAW_ENCRYPTED(drro->drr_flags)) {
|
if (rwa->raw) {
|
||||||
/*
|
/*
|
||||||
* Set the indirect block shift and nlevels. This will not fail
|
* Set the indirect block shift and nlevels. This will not fail
|
||||||
* because we ensured all of the blocks were free earlier if
|
* because we ensured all of the blocks were free earlier if
|
||||||
@ -2518,7 +2518,7 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
|
|||||||
dmu_buf_t *db;
|
dmu_buf_t *db;
|
||||||
uint32_t flags = DMU_READ_NO_PREFETCH;
|
uint32_t flags = DMU_READ_NO_PREFETCH;
|
||||||
|
|
||||||
if (DRR_IS_RAW_ENCRYPTED(drro->drr_flags))
|
if (rwa->raw)
|
||||||
flags |= DMU_READ_NO_DECRYPT;
|
flags |= DMU_READ_NO_DECRYPT;
|
||||||
|
|
||||||
VERIFY0(dmu_bonus_hold_impl(rwa->os, drro->drr_object,
|
VERIFY0(dmu_bonus_hold_impl(rwa->os, drro->drr_object,
|
||||||
@ -2532,7 +2532,7 @@ receive_object(struct receive_writer_arg *rwa, struct drr_object *drro,
|
|||||||
* Raw bonus buffers have their byteorder determined by the
|
* Raw bonus buffers have their byteorder determined by the
|
||||||
* DRR_OBJECT_RANGE record.
|
* DRR_OBJECT_RANGE record.
|
||||||
*/
|
*/
|
||||||
if (rwa->byteswap && !DRR_IS_RAW_ENCRYPTED(drro->drr_flags)) {
|
if (rwa->byteswap && !rwa->raw) {
|
||||||
dmu_object_byteswap_t byteswap =
|
dmu_object_byteswap_t byteswap =
|
||||||
DMU_OT_BYTESWAP(drro->drr_bonustype);
|
DMU_OT_BYTESWAP(drro->drr_bonustype);
|
||||||
dmu_ot_byteswap[byteswap].ob_func(db->db_data,
|
dmu_ot_byteswap[byteswap].ob_func(db->db_data,
|
||||||
@ -2615,6 +2615,10 @@ receive_write(struct receive_writer_arg *rwa, struct drr_write *drrw,
|
|||||||
dmu_tx_abort(tx);
|
dmu_tx_abort(tx);
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rwa->raw)
|
||||||
|
VERIFY0(dmu_object_dirty_raw(rwa->os, drrw->drr_object, tx));
|
||||||
|
|
||||||
if (rwa->byteswap && !arc_is_encrypted(abuf) &&
|
if (rwa->byteswap && !arc_is_encrypted(abuf) &&
|
||||||
arc_get_compression(abuf) == ZIO_COMPRESS_OFF) {
|
arc_get_compression(abuf) == ZIO_COMPRESS_OFF) {
|
||||||
dmu_object_byteswap_t byteswap =
|
dmu_object_byteswap_t byteswap =
|
||||||
@ -2680,9 +2684,8 @@ receive_write_byref(struct receive_writer_arg *rwa,
|
|||||||
ref_os = rwa->os;
|
ref_os = rwa->os;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DRR_IS_RAW_ENCRYPTED(drrwbr->drr_flags)) {
|
if (rwa->raw)
|
||||||
flags |= DMU_READ_NO_DECRYPT;
|
flags |= DMU_READ_NO_DECRYPT;
|
||||||
}
|
|
||||||
|
|
||||||
/* may return either a regular db or an encrypted one */
|
/* may return either a regular db or an encrypted one */
|
||||||
err = dmu_buf_hold(ref_os, drrwbr->drr_refobject,
|
err = dmu_buf_hold(ref_os, drrwbr->drr_refobject,
|
||||||
@ -2700,7 +2703,8 @@ receive_write_byref(struct receive_writer_arg *rwa,
|
|||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DRR_IS_RAW_ENCRYPTED(drrwbr->drr_flags)) {
|
if (rwa->raw) {
|
||||||
|
VERIFY0(dmu_object_dirty_raw(rwa->os, drrwbr->drr_object, tx));
|
||||||
dmu_copy_from_buf(rwa->os, drrwbr->drr_object,
|
dmu_copy_from_buf(rwa->os, drrwbr->drr_object,
|
||||||
drrwbr->drr_offset, dbp, tx);
|
drrwbr->drr_offset, dbp, tx);
|
||||||
} else {
|
} else {
|
||||||
@ -2766,7 +2770,7 @@ receive_spill(struct receive_writer_arg *rwa, struct drr_spill *drrs,
|
|||||||
drrs->drr_length > spa_maxblocksize(dmu_objset_spa(rwa->os)))
|
drrs->drr_length > spa_maxblocksize(dmu_objset_spa(rwa->os)))
|
||||||
return (SET_ERROR(EINVAL));
|
return (SET_ERROR(EINVAL));
|
||||||
|
|
||||||
if (DRR_IS_RAW_ENCRYPTED(drrs->drr_flags)) {
|
if (rwa->raw) {
|
||||||
if (!DMU_OT_IS_VALID(drrs->drr_type) ||
|
if (!DMU_OT_IS_VALID(drrs->drr_type) ||
|
||||||
drrs->drr_compressiontype >= ZIO_COMPRESS_FUNCTIONS ||
|
drrs->drr_compressiontype >= ZIO_COMPRESS_FUNCTIONS ||
|
||||||
drrs->drr_compressed_size == 0)
|
drrs->drr_compressed_size == 0)
|
||||||
@ -2794,6 +2798,8 @@ receive_spill(struct receive_writer_arg *rwa, struct drr_spill *drrs,
|
|||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
dmu_buf_will_dirty(db_spill, tx);
|
dmu_buf_will_dirty(db_spill, tx);
|
||||||
|
if (rwa->raw)
|
||||||
|
VERIFY0(dmu_object_dirty_raw(rwa->os, drrs->drr_object, tx));
|
||||||
|
|
||||||
if (db_spill->db_size < drrs->drr_length)
|
if (db_spill->db_size < drrs->drr_length)
|
||||||
VERIFY(0 == dbuf_spill_set_blksz(db_spill,
|
VERIFY(0 == dbuf_spill_set_blksz(db_spill,
|
||||||
@ -2859,7 +2865,7 @@ receive_object_range(struct receive_writer_arg *rwa,
|
|||||||
*/
|
*/
|
||||||
if (drror->drr_numslots != DNODES_PER_BLOCK ||
|
if (drror->drr_numslots != DNODES_PER_BLOCK ||
|
||||||
P2PHASE(drror->drr_firstobj, DNODES_PER_BLOCK) != 0 ||
|
P2PHASE(drror->drr_firstobj, DNODES_PER_BLOCK) != 0 ||
|
||||||
!DRR_IS_RAW_ENCRYPTED(drror->drr_flags))
|
!rwa->raw)
|
||||||
return (SET_ERROR(EINVAL));
|
return (SET_ERROR(EINVAL));
|
||||||
|
|
||||||
offset = drror->drr_firstobj * sizeof (dnode_phys_t);
|
offset = drror->drr_firstobj * sizeof (dnode_phys_t);
|
||||||
@ -3143,7 +3149,7 @@ receive_read_record(struct receive_arg *ra)
|
|||||||
arc_buf_t *abuf;
|
arc_buf_t *abuf;
|
||||||
boolean_t is_meta = DMU_OT_IS_METADATA(drrw->drr_type);
|
boolean_t is_meta = DMU_OT_IS_METADATA(drrw->drr_type);
|
||||||
|
|
||||||
if (DRR_IS_RAW_ENCRYPTED(drrw->drr_flags)) {
|
if (ra->raw) {
|
||||||
boolean_t byteorder = ZFS_HOST_BYTEORDER ^
|
boolean_t byteorder = ZFS_HOST_BYTEORDER ^
|
||||||
!!DRR_IS_RAW_BYTESWAPPED(drrw->drr_flags) ^
|
!!DRR_IS_RAW_BYTESWAPPED(drrw->drr_flags) ^
|
||||||
ra->byteswap;
|
ra->byteswap;
|
||||||
@ -3227,7 +3233,7 @@ receive_read_record(struct receive_arg *ra)
|
|||||||
int len = DRR_SPILL_PAYLOAD_SIZE(drrs);
|
int len = DRR_SPILL_PAYLOAD_SIZE(drrs);
|
||||||
|
|
||||||
/* DRR_SPILL records are either raw or uncompressed */
|
/* DRR_SPILL records are either raw or uncompressed */
|
||||||
if (DRR_IS_RAW_ENCRYPTED(drrs->drr_flags)) {
|
if (ra->raw) {
|
||||||
boolean_t byteorder = ZFS_HOST_BYTEORDER ^
|
boolean_t byteorder = ZFS_HOST_BYTEORDER ^
|
||||||
!!DRR_IS_RAW_BYTESWAPPED(drrs->drr_flags) ^
|
!!DRR_IS_RAW_BYTESWAPPED(drrs->drr_flags) ^
|
||||||
ra->byteswap;
|
ra->byteswap;
|
||||||
@ -3529,6 +3535,7 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, vnode_t *vp, offset_t *voffp,
|
|||||||
rwa = kmem_zalloc(sizeof (*rwa), KM_SLEEP);
|
rwa = kmem_zalloc(sizeof (*rwa), KM_SLEEP);
|
||||||
|
|
||||||
ra->byteswap = drc->drc_byteswap;
|
ra->byteswap = drc->drc_byteswap;
|
||||||
|
ra->raw = drc->drc_raw;
|
||||||
ra->cksum = drc->drc_cksum;
|
ra->cksum = drc->drc_cksum;
|
||||||
ra->vp = vp;
|
ra->vp = vp;
|
||||||
ra->voff = *voffp;
|
ra->voff = *voffp;
|
||||||
@ -3556,16 +3563,23 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, vnode_t *vp, offset_t *voffp,
|
|||||||
featureflags = DMU_GET_FEATUREFLAGS(drc->drc_drrb->drr_versioninfo);
|
featureflags = DMU_GET_FEATUREFLAGS(drc->drc_drrb->drr_versioninfo);
|
||||||
ra->featureflags = featureflags;
|
ra->featureflags = featureflags;
|
||||||
|
|
||||||
|
/* embedded data is incompatible with encrypted datasets */
|
||||||
|
if (ra->os->os_encrypted &&
|
||||||
|
(featureflags & DMU_BACKUP_FEATURE_EMBED_DATA)) {
|
||||||
|
err = SET_ERROR(EINVAL);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* if this stream is dedup'ed, set up the avl tree for guid mapping */
|
/* if this stream is dedup'ed, set up the avl tree for guid mapping */
|
||||||
if (featureflags & DMU_BACKUP_FEATURE_DEDUP) {
|
if (featureflags & DMU_BACKUP_FEATURE_DEDUP) {
|
||||||
minor_t minor;
|
minor_t minor;
|
||||||
|
|
||||||
if (cleanup_fd == -1) {
|
if (cleanup_fd == -1) {
|
||||||
ra->err = SET_ERROR(EBADF);
|
err = SET_ERROR(EBADF);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ra->err = zfs_onexit_fd_hold(cleanup_fd, &minor);
|
err = zfs_onexit_fd_hold(cleanup_fd, &minor);
|
||||||
if (ra->err != 0) {
|
if (err != 0) {
|
||||||
cleanup_fd = -1;
|
cleanup_fd = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -3579,12 +3593,12 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, vnode_t *vp, offset_t *voffp,
|
|||||||
err = zfs_onexit_add_cb(minor,
|
err = zfs_onexit_add_cb(minor,
|
||||||
free_guid_map_onexit, rwa->guid_to_ds_map,
|
free_guid_map_onexit, rwa->guid_to_ds_map,
|
||||||
action_handlep);
|
action_handlep);
|
||||||
if (ra->err != 0)
|
if (err != 0)
|
||||||
goto out;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
err = zfs_onexit_cb_data(minor, *action_handlep,
|
err = zfs_onexit_cb_data(minor, *action_handlep,
|
||||||
(void **)&rwa->guid_to_ds_map);
|
(void **)&rwa->guid_to_ds_map);
|
||||||
if (ra->err != 0)
|
if (err != 0)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3640,6 +3654,7 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, vnode_t *vp, offset_t *voffp,
|
|||||||
rwa->os = ra->os;
|
rwa->os = ra->os;
|
||||||
rwa->byteswap = drc->drc_byteswap;
|
rwa->byteswap = drc->drc_byteswap;
|
||||||
rwa->resumable = drc->drc_resumable;
|
rwa->resumable = drc->drc_resumable;
|
||||||
|
rwa->raw = drc->drc_raw;
|
||||||
|
|
||||||
(void) thread_create(NULL, 0, receive_writer_thread, rwa, 0, curproc,
|
(void) thread_create(NULL, 0, receive_writer_thread, rwa, 0, curproc,
|
||||||
TS_RUN, minclsyspri);
|
TS_RUN, minclsyspri);
|
||||||
|
Loading…
Reference in New Issue
Block a user