Skip to content

Commit

Permalink
Separate warning for incomplete and corrupt streams
Browse files Browse the repository at this point in the history
This change adds a separate return code to zfs_ioc_recv that is used 
for incomplete streams, in addition to the existing return code for 
streams that contain corruption.

Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Matthew Ahrens <[email protected]>
Signed-off-by: Paul Dagnelie <[email protected]>
Closes openzfs#10122
  • Loading branch information
pcd1193182 authored Mar 17, 2020
1 parent 5b3b795 commit 7145123
Show file tree
Hide file tree
Showing 8 changed files with 24 additions and 11 deletions.
1 change: 1 addition & 0 deletions contrib/pyzfs/libzfs_core/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def enum(*sequential, **named):
'ZFS_ERR_UNKNOWN_SEND_STREAM_FEATURE',
'ZFS_ERR_EXPORT_IN_PROGRESS',
'ZFS_ERR_BOOKMARK_SOURCE_NOT_ANCESTOR',
'ZFS_ERR_STREAM_TRUNCATED',
],
{}
)
Expand Down
2 changes: 2 additions & 0 deletions contrib/pyzfs/libzfs_core/_error_translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,8 @@ def _map(ret, name):
raise lzc_exc.BadStream()
if ret == ZFS_ERR_WRONG_PARENT:
raise lzc_exc.WrongParent(_fs_name(snapname))
if ret == zfs_errno.ZFS_ERR_STREAM_TRUNCATED:
raise lzc_exc.StreamTruncated()

raise lzc_exc.StreamIOError(ret)

Expand Down
8 changes: 7 additions & 1 deletion contrib/pyzfs/libzfs_core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
ZFS_ERR_NO_CHECKPOINT,
ZFS_ERR_DEVRM_IN_PROGRESS,
ZFS_ERR_VDEV_TOO_BIG,
ZFS_ERR_WRONG_PARENT
ZFS_ERR_WRONG_PARENT,
zfs_errno
)


Expand Down Expand Up @@ -351,6 +352,11 @@ class StreamFeatureIncompatible(ZFSError):
message = "Incompatible embedded feature with encrypted receive"


class StreamTruncated(ZFSError):
errno = zfs_errno.ZFS_ERR_STREAM_TRUNCATED
message = "incomplete stream"


class ReceivePropertyFailure(MultipleOperationsFailure):
message = "Receiving of properties failed for one or more reasons"

Expand Down
4 changes: 2 additions & 2 deletions contrib/pyzfs/libzfs_core/test/test_libzfs_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2714,7 +2714,7 @@ def test_send_resume_token_full(self):
lzc.lzc_send(src, None, stream.fileno())
stream.seek(0)
stream.truncate(1024 * 3)
with self.assertRaises(lzc_exc.BadStream):
with self.assertRaises(lzc_exc.StreamTruncated):
lzc.lzc_receive_resumable(dst, stream.fileno())
# Resume token code from zfs_send_resume_token_to_nvlist()
# XXX: if used more than twice move this code into an external func
Expand Down Expand Up @@ -2771,7 +2771,7 @@ def test_send_resume_token_incremental(self):
lzc.lzc_send(snap2, snap1, stream.fileno())
stream.seek(0)
stream.truncate(1024 * 3)
with self.assertRaises(lzc_exc.BadStream):
with self.assertRaises(lzc_exc.StreamTruncated):
lzc.lzc_receive_resumable(dst2, stream.fileno())
# Resume token code from zfs_send_resume_token_to_nvlist()
# format: <version>-<cksum>-<packed-size>-<compressed-payload>
Expand Down
1 change: 1 addition & 0 deletions include/sys/fs/zfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,7 @@ typedef enum {
ZFS_ERR_UNKNOWN_SEND_STREAM_FEATURE,
ZFS_ERR_EXPORT_IN_PROGRESS,
ZFS_ERR_BOOKMARK_SOURCE_NOT_ANCESTOR,
ZFS_ERR_STREAM_TRUNCATED,
} zfs_errno_t;

/*
Expand Down
10 changes: 6 additions & 4 deletions lib/libzfs/libzfs_sendrecv.c
Original file line number Diff line number Diff line change
Expand Up @@ -4253,12 +4253,12 @@ recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)

static void
recv_ecksum_set_aux(libzfs_handle_t *hdl, const char *target_snap,
boolean_t resumable)
boolean_t resumable, boolean_t checksum)
{
char target_fs[ZFS_MAX_DATASET_NAME_LEN];

zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"checksum mismatch or incomplete stream"));
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, (checksum ?
"checksum mismatch" : "incomplete stream")));

if (!resumable)
return;
Expand Down Expand Up @@ -5206,7 +5206,9 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
break;
case ECKSUM:
recv_ecksum_set_aux(hdl, destsnap, flags->resumable);
case ZFS_ERR_STREAM_TRUNCATED:
recv_ecksum_set_aux(hdl, destsnap, flags->resumable,
ioctl_err == ECKSUM);
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
break;
case ENOTSUP:
Expand Down
7 changes: 4 additions & 3 deletions module/zfs/dmu_recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1265,10 +1265,11 @@ receive_read(dmu_recv_cookie_t *drc, int len, void *buf)
len - done, &resid);
if (resid == len - done) {
/*
* Note: ECKSUM indicates that the receive
* was interrupted and can potentially be resumed.
* Note: ECKSUM or ZFS_ERR_STREAM_TRUNCATED indicates
* that the receive was interrupted and can
* potentially be resumed.
*/
drc->drc_err = SET_ERROR(ECKSUM);
drc->drc_err = SET_ERROR(ZFS_ERR_STREAM_TRUNCATED);
}
drc->drc_voff += len - done - resid;
done = len - resid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ test_recv_new(const char *dataset, int fd)
fnvlist_add_boolean(optional, "resumable");
fnvlist_add_uint64(optional, "action_handle", *action_handle);
#endif
IOC_INPUT_TEST(ZFS_IOC_RECV_NEW, dataset, required, optional, ECKSUM);
IOC_INPUT_TEST(ZFS_IOC_RECV_NEW, dataset, required, optional, ZFS_ERR_STREAM_TRUNCATED);

nvlist_free(props);
nvlist_free(optional);
Expand Down

0 comments on commit 7145123

Please sign in to comment.