]> granicus.if.org Git - zfs/commitdiff
'zfs receive' fails with "dataset is busy"
authorLOLi <loli10K@users.noreply.github.com>
Mon, 12 Feb 2018 20:28:59 +0000 (21:28 +0100)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 12 Feb 2018 20:28:59 +0000 (12:28 -0800)
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 #7129
Closes #7154

cmd/zfs/zfs_main.c
lib/libzfs/libzfs_sendrecv.c

index fce228a20981a8aaf9c7d8880a4ddcc9156a013b..991dd444458614e8bfe838386e0549020749a1a0 100644 (file)
@@ -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);
index e12a9db43f918867cd971e7d82cf2e46792a3c54..9ac2a902650b69edcbb68eefa8973aeceba0dcd7 100644 (file)
@@ -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);
@@ -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);
@@ -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);
                }