Skip to content

Commit

Permalink
Send / Recv Fixes following b52563
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Tom Caputi authored and behlendorf committed Aug 23, 2017
1 parent db4c1ad commit 9b84076
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 48 deletions.
5 changes: 3 additions & 2 deletions include/sys/dmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
dmu_tx_t *tx);

void
dmu_write_embedded(objset_t *os, uint64_t object, uint64_t offset,
int dmu_object_dirty_raw(objset_t *os, uint64_t object, dmu_tx_t *tx);

void dmu_write_embedded(objset_t *os, uint64_t object, uint64_t offset,
void *data, uint8_t etype, uint8_t comp, int uncompressed_size,
int compressed_size, int byteorder, dmu_tx_t *tx);

Expand Down
16 changes: 7 additions & 9 deletions include/sys/zfs_ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,9 @@ typedef enum dmu_send_resume_token_version {
* DRR_WRITE_BYREF, and DRR_OBJECT_RANGE blocks
*/
#define DRR_CHECKSUM_DEDUP (1<<0) /* not used for DRR_SPILL blocks */
#define DRR_RAW_ENCRYPTED (1<<1)
#define DRR_RAW_BYTESWAP (1<<2)
#define DRR_RAW_BYTESWAP (1<<1)

#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)

/* deal with compressed drr_write replay records */
Expand All @@ -177,11 +175,11 @@ typedef enum dmu_send_resume_token_version {
(DRR_WRITE_COMPRESSED(drrw) ? (drrw)->drr_compressed_size : \
(drrw)->drr_logical_size)
#define DRR_SPILL_PAYLOAD_SIZE(drrs) \
(DRR_IS_RAW_ENCRYPTED(drrs->drr_flags) ? \
((drrs)->drr_compressed_size ? \
(drrs)->drr_compressed_size : (drrs)->drr_length)
#define DRR_OBJECT_PAYLOAD_SIZE(drro) \
(DRR_IS_RAW_ENCRYPTED(drro->drr_flags) ? \
drro->drr_raw_bonuslen : P2ROUNDUP(drro->drr_bonuslen, 8))
((drro)->drr_raw_bonuslen != 0 ? \
(drro)->drr_raw_bonuslen : P2ROUNDUP((drro)->drr_bonuslen, 8))

/*
* zfs ioctl command structure
Expand Down Expand Up @@ -221,7 +219,7 @@ typedef struct dmu_replay_record {
uint8_t drr_flags;
uint32_t drr_raw_bonuslen;
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_nlevels;
uint8_t drr_nblkptr;
Expand All @@ -247,7 +245,7 @@ typedef struct dmu_replay_record {
ddt_key_t drr_key;
/* only nonzero if drr_compressiontype is not 0 */
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_iv[ZIO_DATA_IV_LEN];
uint8_t drr_mac[ZIO_DATA_MAC_LEN];
Expand Down Expand Up @@ -282,7 +280,7 @@ typedef struct dmu_replay_record {
uint8_t drr_flags;
uint8_t drr_compressiontype;
uint8_t drr_pad[6];
/* only nonzero if DRR_RAW_ENCRYPTED flag is set */
/* only nonzero for raw streams */
uint64_t drr_compressed_size;
uint8_t drr_salt[ZIO_DATA_SALT_LEN];
uint8_t drr_iv[ZIO_DATA_IV_LEN];
Expand Down
6 changes: 6 additions & 0 deletions lib/libzfs/libzfs_sendrecv.c
Original file line number Diff line number Diff line change
Expand Up @@ -3735,6 +3735,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
DMU_BACKUP_FEATURE_RESUMING;
boolean_t raw = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
DMU_BACKUP_FEATURE_RAW;
boolean_t embedded = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
DMU_BACKUP_FEATURE_EMBED_DATA;
stream_wantsnewfs = (drrb->drr_fromguid == 0 ||
(drrb->drr_flags & DRR_FLAG_CLONE) || originsnap) && !resuming;

Expand Down Expand Up @@ -4132,6 +4134,10 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"kernel modules must be upgraded to "
"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);
break;
case ECKSUM:
Expand Down
3 changes: 2 additions & 1 deletion man/man8/zfs.8
Original file line number Diff line number Diff line change
Expand Up @@ -3338,7 +3338,8 @@ feature enabled.
If the
.Sy lz4_compress
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
.Xr zpool-features 5
for details on ZFS feature flags and the
Expand Down
19 changes: 19 additions & 0 deletions module/zfs/dmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2016,6 +2016,25 @@ dmu_object_set_compress(objset_t *os, uint64_t object, uint8_t compress,
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;

/*
Expand Down
Loading

0 comments on commit 9b84076

Please sign in to comment.