mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2025-04-06 17:49:11 +03:00
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:
parent
57858fb5ca
commit
835db58592
@ -3995,13 +3995,11 @@ zfs_do_send(int argc, char **argv)
|
|||||||
if (strchr(argv[0], '@') == NULL ||
|
if (strchr(argv[0], '@') == NULL ||
|
||||||
(fromname && strchr(fromname, '#') != NULL)) {
|
(fromname && strchr(fromname, '#') != NULL)) {
|
||||||
char frombuf[ZFS_MAX_DATASET_NAME_LEN];
|
char frombuf[ZFS_MAX_DATASET_NAME_LEN];
|
||||||
enum lzc_send_flags lzc_flags = 0;
|
|
||||||
|
|
||||||
if (flags.replicate || flags.doall || flags.props ||
|
if (flags.replicate || flags.doall || flags.props ||
|
||||||
flags.dedup || flags.dryrun || flags.verbose ||
|
flags.dedup || (strchr(argv[0], '@') == NULL &&
|
||||||
flags.progress) {
|
(flags.dryrun || flags.verbose || flags.progress))) {
|
||||||
(void) fprintf(stderr,
|
(void) fprintf(stderr, gettext("Error: "
|
||||||
gettext("Error: "
|
|
||||||
"Unsupported flag with filesystem or bookmark.\n"));
|
"Unsupported flag with filesystem or bookmark.\n"));
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
@ -4010,15 +4008,6 @@ zfs_do_send(int argc, char **argv)
|
|||||||
if (zhp == NULL)
|
if (zhp == NULL)
|
||||||
return (1);
|
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 &&
|
if (fromname != NULL &&
|
||||||
(fromname[0] == '#' || fromname[0] == '@')) {
|
(fromname[0] == '#' || fromname[0] == '@')) {
|
||||||
/*
|
/*
|
||||||
@ -4032,7 +4021,7 @@ zfs_do_send(int argc, char **argv)
|
|||||||
(void) strlcat(frombuf, fromname, sizeof (frombuf));
|
(void) strlcat(frombuf, fromname, sizeof (frombuf));
|
||||||
fromname = 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);
|
zfs_close(zhp);
|
||||||
return (err != 0);
|
return (err != 0);
|
||||||
}
|
}
|
||||||
|
@ -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 *,
|
extern int zfs_send(zfs_handle_t *, const char *, const char *,
|
||||||
sendflags_t *, int, snapfilter_cb_t, void *, nvlist_t **);
|
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,
|
extern int zfs_send_resume(libzfs_handle_t *, sendflags_t *, int outfd,
|
||||||
const char *);
|
const char *);
|
||||||
extern nvlist_t *zfs_send_resume_token_to_nvlist(libzfs_handle_t *hdl,
|
extern nvlist_t *zfs_send_resume_token_to_nvlist(libzfs_handle_t *hdl,
|
||||||
|
@ -1242,16 +1242,14 @@ send_print_verbose(FILE *fout, const char *tosnap, const char *fromsnap,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size != 0) {
|
if (parsable) {
|
||||||
if (parsable) {
|
(void) fprintf(fout, "\t%llu",
|
||||||
(void) fprintf(fout, "\t%llu",
|
(longlong_t)size);
|
||||||
(longlong_t)size);
|
} else if (size != 0) {
|
||||||
} else {
|
char buf[16];
|
||||||
char buf[16];
|
zfs_nicebytes(size, buf, sizeof (buf));
|
||||||
zfs_nicebytes(size, buf, sizeof (buf));
|
(void) fprintf(fout, dgettext(TEXT_DOMAIN,
|
||||||
(void) fprintf(fout, dgettext(TEXT_DOMAIN,
|
" estimated size is %s"), buf);
|
||||||
" estimated size is %s"), buf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
(void) fprintf(fout, "\n");
|
(void) fprintf(fout, "\n");
|
||||||
}
|
}
|
||||||
@ -2113,17 +2111,42 @@ err_out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
zfs_send_one(zfs_handle_t *zhp, const char *from, int fd,
|
zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t flags)
|
||||||
enum lzc_send_flags flags)
|
|
||||||
{
|
{
|
||||||
int err;
|
int err = 0;
|
||||||
libzfs_handle_t *hdl = zhp->zfs_hdl;
|
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];
|
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,
|
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
||||||
"warning: cannot send '%s'"), zhp->zfs_name);
|
"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) {
|
if (err != 0) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EXDEV:
|
case EXDEV:
|
||||||
|
@ -171,7 +171,7 @@
|
|||||||
.Ar snapshot
|
.Ar snapshot
|
||||||
.Nm
|
.Nm
|
||||||
.Cm send
|
.Cm send
|
||||||
.Op Fl Lcew
|
.Op Fl LPcenvw
|
||||||
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
|
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
|
||||||
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
|
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
|
||||||
.Nm
|
.Nm
|
||||||
@ -3253,14 +3253,14 @@ The receiving system must also support this feature.
|
|||||||
.It Fl v, -verbose
|
.It Fl v, -verbose
|
||||||
Print verbose information about the stream package generated.
|
Print verbose information about the stream package generated.
|
||||||
This information includes a per-second report of how much data has been sent.
|
This information includes a per-second report of how much data has been sent.
|
||||||
.El
|
|
||||||
.Pp
|
.Pp
|
||||||
The format of the stream is committed.
|
The format of the stream is committed.
|
||||||
You will be able to receive your streams on future versions of ZFS.
|
You will be able to receive your streams on future versions of ZFS.
|
||||||
|
.El
|
||||||
.It Xo
|
.It Xo
|
||||||
.Nm
|
.Nm
|
||||||
.Cm send
|
.Cm send
|
||||||
.Op Fl Lce
|
.Op Fl LPcenvw
|
||||||
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
|
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
|
||||||
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
|
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
|
||||||
.Xc
|
.Xc
|
||||||
@ -3287,6 +3287,8 @@ See
|
|||||||
for details on ZFS feature flags and the
|
for details on ZFS feature flags and the
|
||||||
.Sy large_blocks
|
.Sy large_blocks
|
||||||
feature.
|
feature.
|
||||||
|
.It Fl P, -parsable
|
||||||
|
Print machine-parsable verbose information about the stream package generated.
|
||||||
.It Fl c, -compressed
|
.It Fl c, -compressed
|
||||||
Generate a more compact stream by using compressed WRITE records for blocks
|
Generate a more compact stream by using compressed WRITE records for blocks
|
||||||
which are compressed on disk and in memory
|
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
|
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
|
snapshot, or an earlier snapshot in the origin's filesystem, or the origin's
|
||||||
origin, etc.
|
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
|
.El
|
||||||
.It Xo
|
.It Xo
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -60,10 +60,8 @@ function get_estimate_size
|
|||||||
typeset total_size=$(zfs send $option $base_snapshot $snapshot \
|
typeset total_size=$(zfs send $option $base_snapshot $snapshot \
|
||||||
2>&1 | tail -1)
|
2>&1 | tail -1)
|
||||||
fi
|
fi
|
||||||
if [[ $options == *"P"* ]]; then
|
total_size=$(echo "$total_size" | awk '{print $NF}')
|
||||||
total_size=$(echo "$total_size" | awk '{print $2}')
|
if [[ $options != *"P"* ]]; then
|
||||||
else
|
|
||||||
total_size=$(echo "$total_size" | awk '{print $5}')
|
|
||||||
total_size=${total_size%M}
|
total_size=${total_size%M}
|
||||||
total_size=$(echo "$total_size * $block_count" | bc)
|
total_size=$(echo "$total_size * $block_count" | bc)
|
||||||
fi
|
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 \
|
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS1/file$block_size \
|
||||||
bs=1M count=$block_size
|
bs=1M count=$block_size
|
||||||
log_must zfs snapshot $TESTPOOL/$TESTFS1@snap$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
|
done
|
||||||
|
|
||||||
full_snapshot="$TESTPOOL/$TESTFS1@snap64"
|
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)
|
full_size=$(zfs send $full_snapshot 2>&1 | wc -c)
|
||||||
increamental_size=$(zfs send $increamental_snapshot 2>&1 | wc -c)
|
incremental_size=$(zfs send $incremental_snapshot 2>&1 | wc -c)
|
||||||
increamental_send=$(zfs send -i $full_snapshot $increamental_snapshot 2>&1 | wc -c)
|
incremental_send=$(zfs send -i $full_snapshot $incremental_snapshot 2>&1 | wc -c)
|
||||||
|
|
||||||
log_note "verify zfs send -nv"
|
log_note "verify zfs send -nv"
|
||||||
options="-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"
|
log_note "verify zfs send -nv for multiple snapshot send"
|
||||||
options="-nv"
|
options="-nv"
|
||||||
refer_size=$(get_prop refer $increamental_snapshot)
|
refer_size=$(get_prop refer $incremental_snapshot)
|
||||||
|
|
||||||
estimate_size=$(get_estimate_size $increamental_snapshot $options)
|
estimate_size=$(get_estimate_size $incremental_snapshot $options)
|
||||||
log_must verify_size_estimates $options $increamental_size
|
log_must verify_size_estimates $options $incremental_size
|
||||||
|
|
||||||
log_note "verify zfs send -vPn for multiple snapshot send"
|
log_note "verify zfs send -vPn for multiple snapshot send"
|
||||||
options="-vPn"
|
options="-vPn"
|
||||||
|
|
||||||
estimate_size=$(get_estimate_size $increamental_snapshot $options)
|
estimate_size=$(get_estimate_size $incremental_snapshot $options)
|
||||||
log_must verify_size_estimates $options $increamental_size
|
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"
|
options="-nvi"
|
||||||
refer_size=$(get_prop refer $increamental_snapshot)
|
refer_size=$(get_prop refer $incremental_snapshot)
|
||||||
deduct_size=$(get_prop refer $full_snapshot)
|
deduct_size=$(get_prop refer $full_snapshot)
|
||||||
refer_size=$(echo "$refer_size - $deduct_size" | bc)
|
refer_size=$(echo "$refer_size - $deduct_size" | bc)
|
||||||
|
|
||||||
estimate_size=$(get_estimate_size $increamental_snapshot $options $full_snapshot)
|
estimate_size=$(get_estimate_size $incremental_snapshot $options $full_snapshot)
|
||||||
log_must verify_size_estimates $options $increamental_send
|
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"
|
options="-vPni"
|
||||||
|
|
||||||
estimate_size=$(get_estimate_size $increamental_snapshot $options $full_snapshot)
|
estimate_size=$(get_estimate_size $incremental_snapshot $options $full_snapshot)
|
||||||
log_must verify_size_estimates $options $increamental_send
|
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
|
log_must zfs destroy -r $TESTPOOL/$TESTFS1
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user