Skip to content

Commit

Permalink
Add -vnP support to 'zfs send' for bookmarks
Browse files Browse the repository at this point in the history
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 openzfs#3666 
Closes openzfs#6601
  • Loading branch information
loli10K authored and FransUrbo committed Apr 28, 2019
1 parent c80717a commit 77e6c9c
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 53 deletions.
19 changes: 4 additions & 15 deletions cmd/zfs/zfs_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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] == '@')) {
/*
Expand All @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion include/libzfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,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,
Expand Down
53 changes: 38 additions & 15 deletions lib/libzfs/libzfs_sendrecv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down Expand Up @@ -2114,17 +2112,42 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
}

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:
Expand Down
25 changes: 22 additions & 3 deletions man/man8/zfs.8
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -3265,14 +3265,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
Expand All @@ -3299,6 +3299,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
Expand Down Expand Up @@ -3372,6 +3374,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"
Expand All @@ -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

Expand Down

0 comments on commit 77e6c9c

Please sign in to comment.