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 <behlendorf1@llnl.gov>
Signed-off-by: loli10K <ezomori.nozomu@gmail.com>
Closes #3666 
Closes #6601
This commit is contained in:
LOLi 2017-09-09 00:24:31 +02:00 committed by Brian Behlendorf
parent 57858fb5ca
commit 835db58592
5 changed files with 90 additions and 53 deletions

View 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);
}

View 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,

View File

@ -1242,17 +1242,15 @@ 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 {
} 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:

View File

@ -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

View File

@ -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