summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCedric Maunoury <[email protected]>2021-02-24 18:48:58 +0100
committerGitHub <[email protected]>2021-02-24 09:48:58 -0800
commitb9c07ec71b205c034e63f34fa3546437ea766b3b (patch)
tree1a3f800327f72bc444ab00e6e877b17a5ec6d884
parent9312e0fd1e162094ba2470408878879fa24eeaf7 (diff)
send_iterate_snap : doall send without fromsnap
The behavior of a NULL fromsnap was inadvertently changed for a doall send when the send/recv logic in libzfs was updated. Restore the previous behavior by correcting send_iterate_snap() to include all the snapshots in the nvlist for this case. Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Cedric Maunoury <[email protected]> Closes #11608
-rw-r--r--configure.ac1
-rw-r--r--lib/libzfs/libzfs_sendrecv.c9
-rw-r--r--tests/runfiles/common.run2
-rw-r--r--tests/zfs-tests/cmd/Makefile.am1
-rw-r--r--tests/zfs-tests/cmd/send_doall/.gitignore1
-rw-r--r--tests/zfs-tests/cmd/send_doall/Makefile.am11
-rw-r--r--tests/zfs-tests/cmd/send_doall/send_doall.c87
-rw-r--r--tests/zfs-tests/include/commands.cfg1
-rw-r--r--tests/zfs-tests/tests/functional/rsend/Makefile.am4
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_doall.ksh67
10 files changed, 182 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index 4520a290a..b2d88554e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -230,6 +230,7 @@ AC_CONFIG_FILES([
tests/zfs-tests/cmd/readmmap/Makefile
tests/zfs-tests/cmd/rename_dir/Makefile
tests/zfs-tests/cmd/rm_lnkcnt_zero_file/Makefile
+ tests/zfs-tests/cmd/send_doall/Makefile
tests/zfs-tests/cmd/stride_dd/Makefile
tests/zfs-tests/cmd/threadsappend/Makefile
tests/zfs-tests/cmd/user_ns_exec/Makefile
diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c
index 62a942644..1e3a0bf56 100644
--- a/lib/libzfs/libzfs_sendrecv.c
+++ b/lib/libzfs/libzfs_sendrecv.c
@@ -321,6 +321,15 @@ send_iterate_snap(zfs_handle_t *zhp, void *arg)
}
if (!sd->recursive) {
+
+ /*
+ * To allow a doall stream to work properly
+ * with a NULL fromsnap
+ */
+ if (sd->doall && sd->fromsnap == NULL && !sd->seenfrom) {
+ sd->seenfrom = B_TRUE;
+ }
+
if (!sd->seenfrom && isfromsnap) {
sd->seenfrom = B_TRUE;
zfs_close(zhp);
diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run
index e656785d9..2fffd7a45 100644
--- a/tests/runfiles/common.run
+++ b/tests/runfiles/common.run
@@ -807,7 +807,7 @@ tests = ['recv_dedup', 'recv_dedup_encrypted_zvol', 'rsend_001_pos',
'send_freeobjects', 'send_realloc_files',
'send_realloc_encrypted_files', 'send_spill_block', 'send_holds',
'send_hole_birth', 'send_mixed_raw', 'send-wR_encrypted_zvol',
- 'send_partial_dataset', 'send_invalid']
+ 'send_partial_dataset', 'send_invalid', 'send_doall']
tags = ['functional', 'rsend']
[tests/functional/scrub_mirror]
diff --git a/tests/zfs-tests/cmd/Makefile.am b/tests/zfs-tests/cmd/Makefile.am
index 7fe9a2c57..2b965ca70 100644
--- a/tests/zfs-tests/cmd/Makefile.am
+++ b/tests/zfs-tests/cmd/Makefile.am
@@ -25,6 +25,7 @@ SUBDIRS = \
readmmap \
rename_dir \
rm_lnkcnt_zero_file \
+ send_doall \
stride_dd \
threadsappend
diff --git a/tests/zfs-tests/cmd/send_doall/.gitignore b/tests/zfs-tests/cmd/send_doall/.gitignore
new file mode 100644
index 000000000..6ba2e603f
--- /dev/null
+++ b/tests/zfs-tests/cmd/send_doall/.gitignore
@@ -0,0 +1 @@
+/send_doall
diff --git a/tests/zfs-tests/cmd/send_doall/Makefile.am b/tests/zfs-tests/cmd/send_doall/Makefile.am
new file mode 100644
index 000000000..33a6b8312
--- /dev/null
+++ b/tests/zfs-tests/cmd/send_doall/Makefile.am
@@ -0,0 +1,11 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
+
+pkgexec_PROGRAMS = send_doall
+
+send_doall_SOURCES = send_doall.c
+send_doall_LDADD = \
+ $(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
+ $(abs_top_builddir)/lib/libzfs/libzfs.la \
+ $(abs_top_builddir)/lib/libnvpair/libnvpair.la
diff --git a/tests/zfs-tests/cmd/send_doall/send_doall.c b/tests/zfs-tests/cmd/send_doall/send_doall.c
new file mode 100644
index 000000000..6f47df047
--- /dev/null
+++ b/tests/zfs-tests/cmd/send_doall/send_doall.c
@@ -0,0 +1,87 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Portions Copyright 2020 iXsystems, Inc.
+ */
+
+/*
+ * Test a corner case : a "doall" send without children datasets.
+ */
+
+#include <libzfs.h>
+#include <libzfs_core.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sysexits.h>
+#include <err.h>
+
+static void
+usage(const char *name)
+{
+ fprintf(stderr, "usage: %s snap\n", name);
+ exit(EX_USAGE);
+}
+
+int
+main(int argc, char const * const argv[])
+{
+ sendflags_t flags = { 0 };
+ libzfs_handle_t *zhdl;
+ zfs_handle_t *zhp;
+ const char *tofull, *fsname, *tosnap, *p;
+ int error;
+
+ if (argc != 2)
+ usage(argv[0]);
+
+ tofull = argv[1];
+
+ p = strchr(tofull, '@');
+ if (p == NULL)
+ usage(argv[0]);
+ tosnap = p + 1;
+
+ fsname = strndup(tofull, p - tofull);
+
+ zhdl = libzfs_init();
+ if (zhdl == NULL)
+ errx(EX_OSERR, "libzfs_init(): %s", libzfs_error_init(errno));
+
+ zhp = zfs_open(zhdl, fsname, ZFS_TYPE_FILESYSTEM);
+ if (zhp == NULL)
+ err(EX_OSERR, "zfs_open(\"%s\")", fsname);
+
+ flags.doall = B_TRUE;
+
+ error = zfs_send(zhp, NULL, tosnap, &flags,
+ STDOUT_FILENO, NULL, NULL, NULL);
+
+ zfs_close(zhp);
+
+ libzfs_fini(zhdl);
+ free((void *)fsname);
+
+ return (error);
+}
diff --git a/tests/zfs-tests/include/commands.cfg b/tests/zfs-tests/include/commands.cfg
index 299653547..a43ddd016 100644
--- a/tests/zfs-tests/include/commands.cfg
+++ b/tests/zfs-tests/include/commands.cfg
@@ -217,6 +217,7 @@ export ZFSTEST_FILES='badsend
readmmap
rename_dir
rm_lnkcnt_zero_file
+ send_doall
threadsappend
user_ns_exec
xattrtest
diff --git a/tests/zfs-tests/tests/functional/rsend/Makefile.am b/tests/zfs-tests/tests/functional/rsend/Makefile.am
index 61be2ec18..94bdd2674 100644
--- a/tests/zfs-tests/tests/functional/rsend/Makefile.am
+++ b/tests/zfs-tests/tests/functional/rsend/Makefile.am
@@ -53,7 +53,8 @@ dist_pkgdata_SCRIPTS = \
send_hole_birth.ksh \
send_invalid.ksh \
send_mixed_raw.ksh \
- send-wR_encrypted_zvol.ksh
+ send-wR_encrypted_zvol.ksh \
+ send_doall.ksh
dist_pkgdata_DATA = \
dedup.zsend.bz2 \
@@ -62,3 +63,4 @@ dist_pkgdata_DATA = \
fs.tar.gz \
rsend.cfg \
rsend.kshlib
+
diff --git a/tests/zfs-tests/tests/functional/rsend/send_doall.ksh b/tests/zfs-tests/tests/functional/rsend/send_doall.ksh
new file mode 100755
index 000000000..e5c3490b3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_doall.ksh
@@ -0,0 +1,67 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2019 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify send_doall stream is properly received
+#
+# Strategy:
+# 1) Create a set of snapshots.
+# 2) Send these snapshots (from origin to the last one) to a file using send_doall.
+# 3) Receive the file to newfs to test if the stream is properly handled.
+#
+
+verify_runnable "both"
+
+log_assert "Verify send_doall stream is correct"
+
+function cleanup
+{
+ rm -f $BACKDIR/fs@*
+ destroy_dataset $POOL/fs "-rR"
+ destroy_dataset $POOL/newfs "-rR"
+}
+
+log_onexit cleanup
+
+log_must zfs create $POOL/fs
+log_must zfs create $POOL/fs/child
+
+# Create 3 files and a snapshot between each file creation.
+for i in {1..3}; do
+ file="/$POOL/fs/file$i"
+ log_must mkfile 16384 $file
+
+ file="/$POOL/fs/child/file$i"
+ log_must mkfile 16384 $file
+
+ log_must zfs snapshot -r $POOL/fs@snap$i
+done
+
+# Snapshot the pool and send it to the new dataset.
+log_must eval "send_doall $POOL/fs@snap3 >$BACKDIR/fs@snap3"
+log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs@snap3"
+
+zfs list $POOL/newfs/child
+if [[ $? -eq 0 ]]; then
+ log_fail "Children dataset should not have been received"
+fi
+
+log_pass "Verify send_doall stream is correct"