From fef66e67a0004cd0bfa27c23dd37b2eb1552b963 Mon Sep 17 00:00:00 2001 From: Turbo Fredriksson Date: Fri, 5 Sep 2014 23:29:36 +0200 Subject: [PATCH] 2668: turbo/issue-2666 - Allow for "zfs receive" to skip existing snapshots by adding the option "-s" to zfs receive. Signed-off-by: Turbo Fredriksson Closes: #2666 --- cmd/zfs/zfs_main.c | 11 +++++++---- include/libzfs.h | 3 +++ lib/libzfs/libzfs_sendrecv.c | 16 ++++++++++++++-- man/man8/zfs.8 | 8 ++++---- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 5ba31139a504..bb06755a36ef 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -247,9 +247,9 @@ get_usage(zfs_help_t idx) case HELP_PROMOTE: return (gettext("\tpromote \n")); case HELP_RECEIVE: - return (gettext("\treceive [-vnFu] \n" - "\treceive [-vnFu] [-d | -e] \n")); + "\treceive [-vnFus] [-d | -e] \n")); case HELP_RENAME: return (gettext("\trename [-f] " "\n" @@ -3853,7 +3853,7 @@ zfs_do_send(int argc, char **argv) } /* - * zfs receive [-vnFu] [-d | -e] + * zfs receive [-vnFus] [-d | -e] * * Restore a backup stream from stdin. */ @@ -3864,8 +3864,11 @@ zfs_do_receive(int argc, char **argv) recvflags_t flags = { 0 }; /* check options */ - while ((c = getopt(argc, argv, ":denuvF")) != -1) { + while ((c = getopt(argc, argv, ":denuvFs")) != -1) { switch (c) { + case 's': + flags.skip = B_TRUE; + break; case 'd': flags.isprefix = B_TRUE; break; diff --git a/include/libzfs.h b/include/libzfs.h index 86578d8ad82d..c0eea4a2f7af 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -674,6 +674,9 @@ typedef struct recvflags { /* do not mount file systems as they are extracted (private) */ boolean_t nomount; + + /* skip existing snapshots */ + boolean_t skip; } recvflags_t; extern int zfs_receive(libzfs_handle_t *, const char *, recvflags_t *, diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 70870f766fbf..a691c52c7a24 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -2862,13 +2862,14 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, zfs_handle_t *zhp; /* - * Destination fs exists. Therefore this should either + * Destination fs exists (and we have not been asked to + * skip existing snapshots). Therefore this should either * be an incremental, or the stream specifies a new fs * (full stream or clone) and they want us to blow it * away (and have therefore specified -F and removed any * snapshots). */ - if (stream_wantsnewfs) { + if (stream_wantsnewfs && !flags->skip) { if (!flags->force) { zcmd_free_nvlists(&zc); zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, @@ -2956,6 +2957,17 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, zc.zc_begin_record = drr_noswap->drr_u.drr_begin; zc.zc_cookie = infd; zc.zc_guid = flags->force; + + if (zfs_dataset_exists(hdl, zc.zc_value, ZFS_TYPE_SNAPSHOT) && + flags->skip) { + (void) printf("skipping snapshot %s - %s already exists\n", + drrb->drr_toname, zc.zc_value); + (void) fflush(stdout); + + zcmd_free_nvlists(&zc); + return (recv_skip(hdl, infd, flags->byteswap)); + } + if (flags->verbose) { (void) printf("%s %s stream of %s into %s\n", flags->dryrun ? "would receive" : "receiving", diff --git a/man/man8/zfs.8 b/man/man8/zfs.8 index 69200fc49be3..b376ecfbab19 100644 --- a/man/man8/zfs.8 +++ b/man/man8/zfs.8 @@ -184,12 +184,12 @@ zfs \- configures ZFS file systems .LP .nf -\fBzfs\fR \fBreceive | recv\fR [\fB-vnFu\fR] \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR +\fBzfs\fR \fBreceive | recv\fR [\fB-vnFus\fR] \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR .fi .LP .nf -\fBzfs\fR \fBreceive | recv\fR [\fB-vnFu\fR] [\fB-d\fR|\fB-e\fR] \fIfilesystem\fR +\fBzfs\fR \fBreceive | recv\fR [\fB-vnFus\fR] [\fB-d\fR|\fB-e\fR] \fIfilesystem\fR .fi .LP @@ -3059,11 +3059,11 @@ then the receiving system must have that feature enabled as well. See .ne 2 .mk .na -\fB\fBzfs receive\fR [\fB-vnFu\fR] \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR\fR +\fB\fBzfs receive\fR [\fB-vnFus\fR] \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR\fR .ad .br .na -\fB\fBzfs receive\fR [\fB-vnFu\fR] [\fB-d\fR|\fB-e\fR] \fIfilesystem\fR\fR +\fB\fBzfs receive\fR [\fB-vnFus\fR] [\fB-d\fR|\fB-e\fR] \fIfilesystem\fR\fR .ad .sp .6 .RS 4n