]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Add -vnP support to 'zfs send' for bookmarks
authorLOLi <loli10K@users.noreply.github.com>
Fri, 8 Sep 2017 22:24:31 +0000 (00:24 +0200)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 8 Sep 2017 22:24:31 +0000 (15:24 -0700)
This leverages the functionality introduced in cf7684b to expose
verbose, dry-run and parsable 'zfs send' options for bookmarks.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: loli10K <ezomori.nozomu@gmail.com>
Closes #3666
Closes #6601

cmd/zfs/zfs_main.c
include/libzfs.h
lib/libzfs/libzfs_sendrecv.c
man/man8/zfs.8
tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh

index be83895187e13c34274deacab5240422eece28ab..4331df40324a339a254124697daf73142a3a67cb 100644 (file)
@@ -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);
        }
index b5c35c491edc6e85c4cef4ccbad4a15f98b7cd0f..df8d738b736b4282f405ed2887ea9a3fd0adc766 100644 (file)
@@ -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,
index fddcd9c02fc855bad18b3bffcf6506d39ea046bc..857abda3db523efe4ee920428e05d0ef8431800b 100644 (file)
@@ -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:
index 89541eed98858a7386a63ff3a2ea50375317038f..eb5b6ffb9082aa3fcdc392a6fb8a766dba20df5f 100644 (file)
 .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
index 801633e1fed61a86e0169bc2928e394cd44438a8..1fe10a760def140e80399558599ec8a3103cac2c 100755 (executable)
@@ -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