MFZoL: Add -vnP support to 'zfs send' for bookmarks

zfsonlinux/zfs@835db58592

We have long supported estimating a size of an incremental stream from a
snapshot.  We should do the same for bookmarks as well.

Obtained from:	ZoL
Author:		loli10K <ezomori.nozomu@gmail.com>
MFC after:	3 days
This commit is contained in:
Andriy Gapon 2019-09-17 13:58:15 +00:00
parent 840fa0f86d
commit 496ba62c36
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=352447
4 changed files with 64 additions and 33 deletions

View File

@ -190,8 +190,8 @@
.Ar snapshot .Ar snapshot
.Nm .Nm
.Cm send .Cm send
.Op Fl Lce .Op Fl LPcenv
.Op Fl i Ar snapshot Ns | Ns 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
.Cm send .Cm send
@ -2766,7 +2766,7 @@ on future versions of
.It Xo .It Xo
.Nm .Nm
.Cm send .Cm send
.Op Fl Lce .Op Fl LPcenv
.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
@ -2780,7 +2780,7 @@ stream generated from a filesystem or volume is received, the default snapshot
name will be name will be
.Pq --head-- . .Pq --head-- .
.Bl -tag -width indent .Bl -tag -width indent
.It Fl i Ar snapshot Ns | Ns bookmark .It Fl i Ar snapshot Ns | Ns Ar bookmark
Generate an incremental send stream. Generate an incremental send stream.
The incremental source must be an earlier The incremental source must be an earlier
snapshot in the destination's history. snapshot in the destination's history.
@ -2792,6 +2792,23 @@ specified as the last component of the name
If the incremental target is a clone, the incremental source can If the incremental target is a clone, the incremental source can
be the origin snapshot, or an earlier snapshot in the origin's filesystem, be the origin snapshot, or an earlier snapshot in the origin's filesystem,
or the origin's origin, etc. 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.
.It Fl L, -large-block .It Fl L, -large-block
Generate a stream which may contain blocks larger than 128KB. Generate a stream which may contain blocks larger than 128KB.
This flag This flag
@ -2808,6 +2825,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 (see the which are compressed on disk and in memory (see the

View File

@ -3928,13 +3928,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);
} }
@ -3943,13 +3941,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 (fromname != NULL && if (fromname != NULL &&
(fromname[0] == '#' || fromname[0] == '@')) { (fromname[0] == '#' || fromname[0] == '@')) {
/* /*
@ -3963,7 +3954,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);
} }

View File

@ -660,7 +660,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,

View File

@ -1190,16 +1190,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_nicenum(size, buf, sizeof (buf));
zfs_nicenum(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");
} }
@ -2037,17 +2035,40 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
} }
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.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: