]>
Commit | Line | Data |
---|---|---|
75b07eca FG |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: LOLi <loli10K@users.noreply.github.com> | |
3 | Date: Mon, 12 Feb 2018 21:28:59 +0100 | |
4 | Subject: [PATCH] 'zfs receive' fails with "dataset is busy" | |
5 | MIME-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | Receiving an incremental stream after an interrupted "zfs receive -s" | |
10 | fails with the message "dataset is busy": this is because we still have | |
11 | the hidden clone ../%recv from the resumable receive. | |
12 | ||
13 | Improve the error message suggesting the existence of a partially | |
14 | complete resumable stream from "zfs receive -s" which can be either | |
15 | aborted ("zfs receive -A") or resumed ("zfs send -t"). | |
16 | ||
17 | Reviewed-by: Giuseppe Di Natale <dinatale2@llnl.gov> | |
18 | Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> | |
19 | Reviewed-by: George Melikov <mail@gmelikov.ru> | |
20 | Signed-off-by: loli10K <ezomori.nozomu@gmail.com> | |
21 | Closes #7129 | |
22 | Closes #7154 | |
23 | (cherry picked from commit 1d805a534b5e1768413a0242b8e92b97cb1a796c) | |
24 | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | |
25 | --- | |
26 | cmd/zfs/zfs_main.c | 2 +- | |
27 | lib/libzfs/libzfs_sendrecv.c | 18 +++++++++++++++++- | |
28 | 2 files changed, 18 insertions(+), 2 deletions(-) | |
29 | ||
30 | diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c | |
31 | index e8fe6a9fa..f57df8581 100644 | |
32 | --- a/cmd/zfs/zfs_main.c | |
33 | +++ b/cmd/zfs/zfs_main.c | |
34 | @@ -6072,7 +6072,7 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol, | |
35 | ||
36 | (void) fprintf(stderr, gettext("cannot %s '%s': " | |
37 | "Contains partially-completed state from " | |
38 | - "\"zfs receive -r\", which can be resumed with " | |
39 | + "\"zfs receive -s\", which can be resumed with " | |
40 | "\"zfs send -t\"\n"), | |
41 | cmdname, zfs_get_name(zhp)); | |
42 | return (1); | |
43 | diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c | |
44 | index ec190022f..66d89067b 100644 | |
45 | --- a/lib/libzfs/libzfs_sendrecv.c | |
46 | +++ b/lib/libzfs/libzfs_sendrecv.c | |
47 | @@ -3254,6 +3254,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, | |
48 | zfs_type_t type; | |
49 | boolean_t toplevel = B_FALSE; | |
50 | boolean_t zoned = B_FALSE; | |
51 | + boolean_t hastoken = B_FALSE; | |
52 | ||
53 | begin_time = time(NULL); | |
54 | bzero(origin, MAXNAMELEN); | |
55 | @@ -3535,6 +3536,11 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, | |
56 | /* we want to know if we're zoned when validating -o|-x props */ | |
57 | zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); | |
58 | ||
59 | + /* may need this info later, get it now we have zhp around */ | |
60 | + if (zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN, NULL, 0, | |
61 | + NULL, NULL, 0, B_TRUE) == 0) | |
62 | + hastoken = B_TRUE; | |
63 | + | |
64 | /* gather existing properties on destination */ | |
65 | origprops = fnvlist_alloc(); | |
66 | fnvlist_merge(origprops, zhp->zfs_props); | |
67 | @@ -3741,9 +3747,19 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, | |
68 | break; | |
69 | case EDQUOT: | |
70 | zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, | |
71 | - "destination %s space quota exceeded"), name); | |
72 | + "destination %s space quota exceeded."), name); | |
73 | (void) zfs_error(hdl, EZFS_NOSPC, errbuf); | |
74 | break; | |
75 | + case EBUSY: | |
76 | + if (hastoken) { | |
77 | + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, | |
78 | + "destination %s contains " | |
79 | + "partially-complete state from " | |
80 | + "\"zfs receive -s\"."), name); | |
81 | + (void) zfs_error(hdl, EZFS_BUSY, errbuf); | |
82 | + break; | |
83 | + } | |
84 | + /* fallthru */ | |
85 | default: | |
86 | (void) zfs_standard_error(hdl, ioctl_errno, errbuf); | |
87 | } | |
88 | -- | |
89 | 2.14.2 | |
90 |