Skip to content

Commit

Permalink
'zfs receive' fails with "dataset is busy"
Browse files Browse the repository at this point in the history
Receiving an incremental stream after an interrupted "zfs receive -s"
fails with the message "dataset is busy": this is because we still have
the hidden clone ../%recv from the resumable receive.

Improve the error message suggesting the existence of a partially
complete resumable stream from "zfs receive -s" which can be either
aborted ("zfs receive -A") or resumed ("zfs send -t").

Reviewed-by: Giuseppe Di Natale <dinatale2@llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: George Melikov <mail@gmelikov.ru>
Signed-off-by: loli10K <ezomori.nozomu@gmail.com>
Closes openzfs#7129
Closes openzfs#7154
  • Loading branch information
loli10K authored and Nasf-Fan committed Feb 13, 2018
1 parent 16261cd commit 9e9c9d7
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 2 deletions.
2 changes: 1 addition & 1 deletion cmd/zfs/zfs_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6123,7 +6123,7 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol,

(void) fprintf(stderr, gettext("cannot %s '%s': "
"Contains partially-completed state from "
"\"zfs receive -r\", which can be resumed with "
"\"zfs receive -s\", which can be resumed with "
"\"zfs send -t\"\n"),
cmdname, zfs_get_name(zhp));
return (1);
Expand Down
18 changes: 17 additions & 1 deletion lib/libzfs/libzfs_sendrecv.c
Original file line number Diff line number Diff line change
Expand Up @@ -3605,6 +3605,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
zfs_type_t type;
boolean_t toplevel = B_FALSE;
boolean_t zoned = B_FALSE;
boolean_t hastoken = B_FALSE;

begin_time = time(NULL);
bzero(origin, MAXNAMELEN);
Expand Down Expand Up @@ -3928,6 +3929,11 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
/* we want to know if we're zoned when validating -o|-x props */
zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);

/* may need this info later, get it now we have zhp around */
if (zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN, NULL, 0,
NULL, NULL, 0, B_TRUE) == 0)
hastoken = B_TRUE;

/* gather existing properties on destination */
origprops = fnvlist_alloc();
fnvlist_merge(origprops, zhp->zfs_props);
Expand Down Expand Up @@ -4186,9 +4192,19 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
break;
case EDQUOT:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"destination %s space quota exceeded"), name);
"destination %s space quota exceeded."), name);
(void) zfs_error(hdl, EZFS_NOSPC, errbuf);
break;
case EBUSY:
if (hastoken) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"destination %s contains "
"partially-complete state from "
"\"zfs receive -s\"."), name);
(void) zfs_error(hdl, EZFS_BUSY, errbuf);
break;
}
/* fallthru */
default:
(void) zfs_standard_error(hdl, ioctl_errno, errbuf);
}
Expand Down

0 comments on commit 9e9c9d7

Please sign in to comment.