Merge from stable/12 r352595: Add -vnP support to 'zfs send' for bookmarks

Approved by:	re (gjb)
This commit is contained in:
avg 2019-09-30 14:19:18 +00:00 committed by Franco Fichtner
parent 7a6f726ddc
commit d310241771
5 changed files with 67 additions and 35 deletions

View file

@ -190,8 +190,8 @@
.Ar snapshot
.Nm
.Cm send
.Op Fl Lce
.Op Fl i Ar snapshot Ns | Ns bookmark
.Op Fl LPcenv
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Nm
.Cm send
@ -2764,7 +2764,7 @@ on future versions of
.It Xo
.Nm
.Cm send
.Op Fl Lce
.Op Fl LPcenv
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Xc
@ -2778,7 +2778,7 @@ stream generated from a filesystem or volume is received, the default snapshot
name will be
.Pq --head-- .
.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.
The incremental source must be an earlier
snapshot in the destination's history.
@ -2790,6 +2790,23 @@ specified as the last component of the name
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.
.It Fl L, -large-block
Generate a stream which may contain blocks larger than 128KB.
This flag
@ -2806,6 +2823,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 (see the

View file

@ -290,7 +290,7 @@ get_usage(zfs_help_t idx)
case HELP_SEND:
return (gettext("\tsend [-DnPpRvLec] [-[iI] snapshot] "
"<snapshot>\n"
"\tsend [-Le] [-i snapshot|bookmark] "
"\tsend [-LPcenv] [-i snapshot|bookmark] "
"<filesystem|volume|snapshot>\n"
"\tsend [-nvPe] -t <receive_resume_token>\n"));
case HELP_SET:
@ -3928,13 +3928,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);
}
@ -3943,13 +3941,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 (fromname != NULL &&
(fromname[0] == '#' || fromname[0] == '@')) {
/*
@ -3963,7 +3954,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

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

@ -1190,16 +1190,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_nicenum(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_nicenum(size, buf, sizeof (buf));
(void) fprintf(fout, dgettext(TEXT_DOMAIN,
" estimated size is %s"), buf);
}
(void) fprintf(fout, "\n");
}
@ -2037,17 +2035,40 @@ 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.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

@ -775,6 +775,7 @@ be_export(libbe_handle_t *lbh, const char *bootenv, int fd)
char snap_name[BE_MAXPATHLEN];
char buf[BE_MAXPATHLEN];
zfs_handle_t *zfs;
sendflags_t flags = { 0 };
int err;
if ((err = be_snapshot(lbh, bootenv, NULL, true, snap_name)) != 0)
@ -786,7 +787,7 @@ be_export(libbe_handle_t *lbh, const char *bootenv, int fd)
if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_DATASET)) == NULL)
return (set_error(lbh, BE_ERR_ZFSOPEN));
err = zfs_send_one(zfs, NULL, fd, 0);
err = zfs_send_one(zfs, NULL, fd, flags);
zfs_close(zfs);
return (err);