Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix noop receive of raw send stream #9221

Merged
merged 1 commit into from Sep 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 33 additions & 6 deletions lib/libzfs/libzfs_sendrecv.c
Expand Up @@ -4042,10 +4042,11 @@ recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
{
dmu_replay_record_t *drr;
void *buf = zfs_alloc(hdl, SPA_MAXBLOCKSIZE);
uint64_t payload_size;
char errbuf[1024];

(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot receive:"));
"cannot receive"));

/* XXX would be great to use lseek if possible... */
drr = buf;
Expand All @@ -4072,9 +4073,14 @@ recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
drr->drr_u.drr_object.drr_bonuslen =
BSWAP_32(drr->drr_u.drr_object.
drr_bonuslen);
drr->drr_u.drr_object.drr_raw_bonuslen =
BSWAP_32(drr->drr_u.drr_object.
drr_raw_bonuslen);
}
(void) recv_read(hdl, fd, buf,
P2ROUNDUP(drr->drr_u.drr_object.drr_bonuslen, 8),

payload_size =
DRR_OBJECT_PAYLOAD_SIZE(&drr->drr_u.drr_object);
(void) recv_read(hdl, fd, buf, payload_size,
B_FALSE, NULL);
break;

Expand All @@ -4087,7 +4093,7 @@ recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
BSWAP_64(
drr->drr_u.drr_write.drr_compressed_size);
}
uint64_t payload_size =
payload_size =
DRR_WRITE_PAYLOAD_SIZE(&drr->drr_u.drr_write);
(void) recv_read(hdl, fd, buf,
payload_size, B_FALSE, NULL);
Expand All @@ -4096,9 +4102,15 @@ recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
if (byteswap) {
drr->drr_u.drr_spill.drr_length =
BSWAP_64(drr->drr_u.drr_spill.drr_length);
drr->drr_u.drr_spill.drr_compressed_size =
BSWAP_64(drr->drr_u.drr_spill.
drr_compressed_size);
}
(void) recv_read(hdl, fd, buf,
drr->drr_u.drr_spill.drr_length, B_FALSE, NULL);

payload_size =
DRR_SPILL_PAYLOAD_SIZE(&drr->drr_u.drr_spill);
(void) recv_read(hdl, fd, buf, payload_size,
B_FALSE, NULL);
break;
case DRR_WRITE_EMBEDDED:
if (byteswap) {
Expand Down Expand Up @@ -4841,6 +4853,21 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
}

if (flags->dryrun) {
void *buf = zfs_alloc(hdl, SPA_MAXBLOCKSIZE);

/*
* We have read the DRR_BEGIN record, but we have
* not yet read the payload. For non-dryrun sends
* this will be done by the kernel, so we must
* emulate that here, before attempting to read
* more records.
*/
err = recv_read(hdl, infd, buf, drr->drr_payloadlen,
flags->byteswap, NULL);
free(buf);
if (err != 0)
goto out;

err = recv_skip(hdl, infd, flags->byteswap);
goto out;
}
Expand Down
Expand Up @@ -36,6 +36,7 @@
# 9. Verify the key is unavailable
# 10. Attempt to load the key and mount the dataset
# 11. Verify the checksum of the file is the same as the original
# 12. Verify 'zfs receive -n' works with the raw stream
#

verify_runnable "both"
Expand Down Expand Up @@ -88,4 +89,6 @@ typeset cksum2=$(md5digest /$TESTPOOL/$TESTFS1/c1/$TESTFILE0)
[[ "$cksum2" == "$checksum" ]] || \
log_fail "Checksums differ ($cksum2 != $checksum)"

log_must eval "zfs send -w $snap | zfs receive -n $TESTPOOL/$TESTFS3"

log_pass "ZFS can receive streams from raw sends"