summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLOLi <[email protected]>2017-09-09 00:24:31 +0200
committerBrian Behlendorf <[email protected]>2017-09-08 15:24:31 -0700
commit835db58592d7d947e5818eb7281882e2a46073e0 (patch)
tree5f99c47d3fa3ab2d18aeafb4b7be90975984f747
parent57858fb5ca4b1d0f28b054cb5e15aaf3bc54c99e (diff)
Add -vnP support to 'zfs send' for bookmarks
This leverages the functionality introduced in cf7684b to expose verbose, dry-run and parsable 'zfs send' options for bookmarks. Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: loli10K <[email protected]> Closes #3666 Closes #6601
-rw-r--r--cmd/zfs/zfs_main.c19
-rw-r--r--include/libzfs.h2
-rw-r--r--lib/libzfs/libzfs_sendrecv.c53
-rw-r--r--man/man8/zfs.825
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh44
5 files changed, 90 insertions, 53 deletions
diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c
index be8389518..4331df403 100644
--- a/cmd/zfs/zfs_main.c
+++ b/cmd/zfs/zfs_main.c
@@ -3995,13 +3995,11 @@ zfs_do_send(int argc, char **argv)
if (strchr(argv[0], '@') == NULL ||
(fromname && strchr(fromname, '#') != NULL)) {
char frombuf[ZFS_MAX_DATASET_NAME_LEN];
- enum lzc_send_flags lzc_flags = 0;
if (flags.replicate || flags.doall || flags.props ||
- flags.dedup || flags.dryrun || flags.verbose ||
- flags.progress) {
- (void) fprintf(stderr,
- gettext("Error: "
+ flags.dedup || (strchr(argv[0], '@') == NULL &&
+ (flags.dryrun || flags.verbose || flags.progress))) {
+ (void) fprintf(stderr, gettext("Error: "
"Unsupported flag with filesystem or bookmark.\n"));
return (1);
}
@@ -4010,15 +4008,6 @@ zfs_do_send(int argc, char **argv)
if (zhp == NULL)
return (1);
- if (flags.largeblock)
- lzc_flags |= LZC_SEND_FLAG_LARGE_BLOCK;
- if (flags.embed_data)
- lzc_flags |= LZC_SEND_FLAG_EMBED_DATA;
- if (flags.compress)
- lzc_flags |= LZC_SEND_FLAG_COMPRESS;
- if (flags.raw)
- lzc_flags |= LZC_SEND_FLAG_RAW;
-
if (fromname != NULL &&
(fromname[0] == '#' || fromname[0] == '@')) {
/*
@@ -4032,7 +4021,7 @@ zfs_do_send(int argc, char **argv)
(void) strlcat(frombuf, fromname, sizeof (frombuf));
fromname = frombuf;
}
- err = zfs_send_one(zhp, fromname, STDOUT_FILENO, lzc_flags);
+ err = zfs_send_one(zhp, fromname, STDOUT_FILENO, flags);
zfs_close(zhp);
return (err != 0);
}
diff --git a/include/libzfs.h b/include/libzfs.h
index b5c35c491..df8d738b7 100644
--- a/include/libzfs.h
+++ b/include/libzfs.h
@@ -677,7 +677,7 @@ typedef boolean_t (snapfilter_cb_t)(zfs_handle_t *, void *);
extern int zfs_send(zfs_handle_t *, const char *, const char *,
sendflags_t *, int, snapfilter_cb_t, void *, nvlist_t **);
-extern int zfs_send_one(zfs_handle_t *, const char *, int, enum lzc_send_flags);
+extern int zfs_send_one(zfs_handle_t *, const char *, int, sendflags_t flags);
extern int zfs_send_resume(libzfs_handle_t *, sendflags_t *, int outfd,
const char *);
extern nvlist_t *zfs_send_resume_token_to_nvlist(libzfs_handle_t *hdl,
diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c
index fddcd9c02..857abda3d 100644
--- a/lib/libzfs/libzfs_sendrecv.c
+++ b/lib/libzfs/libzfs_sendrecv.c
@@ -1242,16 +1242,14 @@ send_print_verbose(FILE *fout, const char *tosnap, const char *fromsnap,
}
}
- if (size != 0) {
- if (parsable) {
- (void) fprintf(fout, "\t%llu",
- (longlong_t)size);
- } else {
- char buf[16];
- zfs_nicebytes(size, buf, sizeof (buf));
- (void) fprintf(fout, dgettext(TEXT_DOMAIN,
- " estimated size is %s"), buf);
- }
+ if (parsable) {
+ (void) fprintf(fout, "\t%llu",
+ (longlong_t)size);
+ } else if (size != 0) {
+ char buf[16];
+ zfs_nicebytes(size, buf, sizeof (buf));
+ (void) fprintf(fout, dgettext(TEXT_DOMAIN,
+ " estimated size is %s"), buf);
}
(void) fprintf(fout, "\n");
}
@@ -2113,17 +2111,42 @@ err_out:
}
int
-zfs_send_one(zfs_handle_t *zhp, const char *from, int fd,
- enum lzc_send_flags flags)
+zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t flags)
{
- int err;
+ int err = 0;
libzfs_handle_t *hdl = zhp->zfs_hdl;
-
+ enum lzc_send_flags lzc_flags = 0;
+ FILE *fout = (flags.verbose && flags.dryrun) ? stdout : stderr;
char errbuf[1024];
+
+ if (flags.largeblock)
+ lzc_flags |= LZC_SEND_FLAG_LARGE_BLOCK;
+ if (flags.embed_data)
+ lzc_flags |= LZC_SEND_FLAG_EMBED_DATA;
+ if (flags.compress)
+ lzc_flags |= LZC_SEND_FLAG_COMPRESS;
+ if (flags.raw)
+ lzc_flags |= LZC_SEND_FLAG_RAW;
+
+ if (flags.verbose) {
+ uint64_t size = 0;
+ err = lzc_send_space(zhp->zfs_name, from, lzc_flags, &size);
+ if (err == 0) {
+ send_print_verbose(fout, zhp->zfs_name, from, size,
+ flags.parsable);
+ } else {
+ (void) fprintf(stderr, "Cannot estimate send size: "
+ "%s\n", strerror(errno));
+ }
+ }
+
+ if (flags.dryrun)
+ return (err);
+
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"warning: cannot send '%s'"), zhp->zfs_name);
- err = lzc_send(zhp->zfs_name, from, fd, flags);
+ err = lzc_send(zhp->zfs_name, from, fd, lzc_flags);
if (err != 0) {
switch (errno) {
case EXDEV:
diff --git a/man/man8/zfs.8 b/man/man8/zfs.8
index 89541eed9..eb5b6ffb9 100644
--- a/man/man8/zfs.8
+++ b/man/man8/zfs.8
@@ -171,7 +171,7 @@
.Ar snapshot
.Nm
.Cm send
-.Op Fl Lcew
+.Op Fl LPcenvw
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Nm
@@ -3253,14 +3253,14 @@ The receiving system must also support this feature.
.It Fl v, -verbose
Print verbose information about the stream package generated.
This information includes a per-second report of how much data has been sent.
-.El
.Pp
The format of the stream is committed.
You will be able to receive your streams on future versions of ZFS.
+.El
.It Xo
.Nm
.Cm send
-.Op Fl Lce
+.Op Fl LPcenvw
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Xc
@@ -3287,6 +3287,8 @@ See
for details on ZFS feature flags and the
.Sy large_blocks
feature.
+.It Fl P, -parsable
+Print machine-parsable verbose information about the stream package generated.
.It Fl c, -compressed
Generate a more compact stream by using compressed WRITE records for blocks
which are compressed on disk and in memory
@@ -3360,6 +3362,23 @@ character and following
If the incremental target is a clone, the incremental source can be the origin
snapshot, or an earlier snapshot in the origin's filesystem, or the origin's
origin, etc.
+.It Fl n, -dryrun
+Do a dry-run
+.Pq Qq No-op
+send.
+Do not generate any actual send data.
+This is useful in conjunction with the
+.Fl v
+or
+.Fl P
+flags to determine what data will be sent.
+In this case, the verbose output will be written to standard output
+.Po contrast with a non-dry-run, where the stream is written to standard output
+and the verbose output goes to standard error
+.Pc .
+.It Fl v, -verbose
+Print verbose information about the stream package generated.
+This information includes a per-second report of how much data has been sent.
.El
.It Xo
.Nm
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh
index 801633e1f..1fe10a760 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh
@@ -60,10 +60,8 @@ function get_estimate_size
typeset total_size=$(zfs send $option $base_snapshot $snapshot \
2>&1 | tail -1)
fi
- if [[ $options == *"P"* ]]; then
- total_size=$(echo "$total_size" | awk '{print $2}')
- else
- total_size=$(echo "$total_size" | awk '{print $5}')
+ total_size=$(echo "$total_size" | awk '{print $NF}')
+ if [[ $options != *"P"* ]]; then
total_size=${total_size%M}
total_size=$(echo "$total_size * $block_count" | bc)
fi
@@ -106,14 +104,18 @@ for block_size in 64 128 256; do
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS1/file$block_size \
bs=1M count=$block_size
log_must zfs snapshot $TESTPOOL/$TESTFS1@snap$block_size
+ log_must zfs bookmark $TESTPOOL/$TESTFS1@snap$block_size \
+ "$TESTPOOL/$TESTFS1#bmark$block_size"
done
full_snapshot="$TESTPOOL/$TESTFS1@snap64"
-increamental_snapshot="$TESTPOOL/$TESTFS1@snap256"
+incremental_snapshot="$TESTPOOL/$TESTFS1@snap256"
+full_bookmark="$TESTPOOL/$TESTFS1#bmark64"
+incremental_bookmark="$TESTPOOL/$TESTFS1#bmark256"
full_size=$(zfs send $full_snapshot 2>&1 | wc -c)
-increamental_size=$(zfs send $increamental_snapshot 2>&1 | wc -c)
-increamental_send=$(zfs send -i $full_snapshot $increamental_snapshot 2>&1 | wc -c)
+incremental_size=$(zfs send $incremental_snapshot 2>&1 | wc -c)
+incremental_send=$(zfs send -i $full_snapshot $incremental_snapshot 2>&1 | wc -c)
log_note "verify zfs send -nv"
options="-nv"
@@ -129,31 +131,35 @@ log_must verify_size_estimates $options $full_size
log_note "verify zfs send -nv for multiple snapshot send"
options="-nv"
-refer_size=$(get_prop refer $increamental_snapshot)
+refer_size=$(get_prop refer $incremental_snapshot)
-estimate_size=$(get_estimate_size $increamental_snapshot $options)
-log_must verify_size_estimates $options $increamental_size
+estimate_size=$(get_estimate_size $incremental_snapshot $options)
+log_must verify_size_estimates $options $incremental_size
log_note "verify zfs send -vPn for multiple snapshot send"
options="-vPn"
-estimate_size=$(get_estimate_size $increamental_snapshot $options)
-log_must verify_size_estimates $options $increamental_size
+estimate_size=$(get_estimate_size $incremental_snapshot $options)
+log_must verify_size_estimates $options $incremental_size
-log_note "verify zfs send -inv for increamental send"
+log_note "verify zfs send -inv for incremental send"
options="-nvi"
-refer_size=$(get_prop refer $increamental_snapshot)
+refer_size=$(get_prop refer $incremental_snapshot)
deduct_size=$(get_prop refer $full_snapshot)
refer_size=$(echo "$refer_size - $deduct_size" | bc)
-estimate_size=$(get_estimate_size $increamental_snapshot $options $full_snapshot)
-log_must verify_size_estimates $options $increamental_send
+estimate_size=$(get_estimate_size $incremental_snapshot $options $full_snapshot)
+log_must verify_size_estimates $options $incremental_send
+estimate_size=$(get_estimate_size $incremental_snapshot $options $full_bookmark)
+log_must verify_size_estimates $options $incremental_send
-log_note "verify zfs send -ivPn for increamental send"
+log_note "verify zfs send -ivPn for incremental send"
options="-vPni"
-estimate_size=$(get_estimate_size $increamental_snapshot $options $full_snapshot)
-log_must verify_size_estimates $options $increamental_send
+estimate_size=$(get_estimate_size $incremental_snapshot $options $full_snapshot)
+log_must verify_size_estimates $options $incremental_send
+estimate_size=$(get_estimate_size $incremental_snapshot $options $full_bookmark)
+log_must verify_size_estimates $options $incremental_send
log_must zfs destroy -r $TESTPOOL/$TESTFS1