aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c')
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c79
1 files changed, 48 insertions, 31 deletions
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c b/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c
index 0e5cecc6cca9..18130a34fea8 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c
@@ -258,7 +258,10 @@ typedef struct send_data {
boolean_t seento;
boolean_t holds; /* were holds requested with send -h */
boolean_t props;
+ boolean_t no_preserve_encryption;
+ snapfilter_cb_t *filter_cb;
+ void *filter_cb_arg;
/*
* The header nvlist is of the following format:
* {
@@ -511,6 +514,10 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
uint64_t fromsnap_txg_save = sd->fromsnap_txg;
uint64_t tosnap_txg_save = sd->tosnap_txg;
+ if (sd->filter_cb &&
+ (sd->filter_cb(zhp, sd->filter_cb_arg) == 0))
+ return (0);
+
fromsnap_txg = get_snap_txg(zhp->zfs_hdl, zhp->zfs_name, sd->fromsnap);
if (fromsnap_txg != 0)
sd->fromsnap_txg = fromsnap_txg;
@@ -587,20 +594,32 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg)
fnvlist_add_boolean(nvfs, "is_encroot");
/*
- * Encrypted datasets can only be sent with properties if
- * the raw flag is specified because the receive side doesn't
- * currently have a mechanism for recursively asking the user
- * for new encryption parameters.
+ * Encrypted datasets can only be sent with properties if the
+ * raw flag or the no-preserve-encryption flag are specified
+ * because the receive side doesn't currently have a mechanism
+ * for recursively asking the user for new encryption
+ * parameters.
+ * We allow sending the dataset unencrypted only if the user
+ * explicitly sets the no-preserve-encryption flag.
*/
- if (!sd->raw) {
+ if (!sd->raw && !sd->no_preserve_encryption) {
(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
"cannot send %s@%s: encrypted dataset %s may not "
- "be sent with properties without the raw flag\n"),
+ "be sent with properties without the raw flag or "
+ "no-preserve-encryption flag\n"),
sd->fsname, sd->tosnap, zhp->zfs_name);
rv = -1;
goto out;
}
+ /* If no-preserve-encryption flag is set, warn the user again */
+ if (!sd->raw && sd->no_preserve_encryption) {
+ (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+ "WARNING: no-preserve-encryption flag set, sending "
+ "dataset %s without encryption\n"),
+ zhp->zfs_name);
+ }
+
}
/*
@@ -683,8 +702,9 @@ static int
gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
const char *tosnap, boolean_t recursive, boolean_t raw, boolean_t doall,
boolean_t replicate, boolean_t skipmissing, boolean_t verbose,
- boolean_t backup, boolean_t holds, boolean_t props, nvlist_t **nvlp,
- avl_tree_t **avlp)
+ boolean_t backup, boolean_t holds, boolean_t props,
+ boolean_t no_preserve_encryption, nvlist_t **nvlp, avl_tree_t **avlp,
+ snapfilter_cb_t *filter_cb, void *filter_cb_arg)
{
zfs_handle_t *zhp;
send_data_t sd = { 0 };
@@ -707,6 +727,9 @@ gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
sd.backup = backup;
sd.holds = holds;
sd.props = props;
+ sd.no_preserve_encryption = no_preserve_encryption;
+ sd.filter_cb = filter_cb;
+ sd.filter_cb_arg = filter_cb_arg;
if ((error = send_iterate_fs(zhp, &sd)) != 0) {
fnvlist_free(sd.fss);
@@ -913,21 +936,8 @@ int
zfs_send_progress(zfs_handle_t *zhp, int fd, uint64_t *bytes_written,
uint64_t *blocks_visited)
{
- zfs_cmd_t zc = {"\0"};
-
- if (bytes_written != NULL)
- *bytes_written = 0;
- if (blocks_visited != NULL)
- *blocks_visited = 0;
- (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
- zc.zc_cookie = fd;
- if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND_PROGRESS, &zc) != 0)
- return (errno);
- if (bytes_written != NULL)
- *bytes_written = zc.zc_cookie;
- if (blocks_visited != NULL)
- *blocks_visited = zc.zc_objset_type;
- return (0);
+ return (lzc_send_progress(zhp->zfs_name, fd, bytes_written,
+ blocks_visited));
}
static volatile boolean_t send_progress_thread_signal_duetotimer;
@@ -2199,7 +2209,8 @@ send_prelim_records(zfs_handle_t *zhp, const char *from, int fd,
boolean_t gather_props, boolean_t recursive, boolean_t verbose,
boolean_t dryrun, boolean_t raw, boolean_t replicate, boolean_t skipmissing,
boolean_t backup, boolean_t holds, boolean_t props, boolean_t doall,
- nvlist_t **fssp, avl_tree_t **fsavlp)
+ boolean_t no_preserve_encryption, nvlist_t **fssp, avl_tree_t **fsavlp,
+ snapfilter_cb_t filter_func, void *cb_arg)
{
int err = 0;
char *packbuf = NULL;
@@ -2245,7 +2256,8 @@ send_prelim_records(zfs_handle_t *zhp, const char *from, int fd,
if (gather_nvlist(zhp->zfs_hdl, tofs,
from, tosnap, recursive, raw, doall, replicate, skipmissing,
- verbose, backup, holds, props, &fss, fsavlp) != 0) {
+ verbose, backup, holds, props, no_preserve_encryption,
+ &fss, fsavlp, filter_func, cb_arg) != 0) {
return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP,
errbuf));
}
@@ -2392,7 +2404,8 @@ zfs_send_cb_impl(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
flags->replicate, flags->verbosity > 0, flags->dryrun,
flags->raw, flags->replicate, flags->skipmissing,
flags->backup, flags->holds, flags->props, flags->doall,
- &fss, &fsavl);
+ flags->no_preserve_encryption, &fss, &fsavl,
+ filter_func, cb_arg);
zfs_close(tosnap);
if (err != 0)
goto err_out;
@@ -2735,7 +2748,8 @@ zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd,
err = send_prelim_records(zhp, NULL, fd, B_TRUE, B_FALSE,
flags->verbosity > 0, flags->dryrun, flags->raw,
flags->replicate, B_FALSE, flags->backup, flags->holds,
- flags->props, flags->doall, NULL, NULL);
+ flags->props, flags->doall, flags->no_preserve_encryption,
+ NULL, NULL, NULL, NULL);
if (err != 0)
return (err);
}
@@ -3392,7 +3406,8 @@ recv_fix_encryption_hierarchy(libzfs_handle_t *hdl, const char *top_zfs,
/* Using top_zfs, gather the nvlists for all local filesystems. */
if ((err = gather_nvlist(hdl, top_zfs, NULL, NULL,
recursive, B_TRUE, B_FALSE, recursive, B_FALSE, B_FALSE, B_FALSE,
- B_FALSE, B_TRUE, &local_nv, &local_avl)) != 0)
+ B_FALSE, B_TRUE, B_FALSE, &local_nv, &local_avl,
+ NULL, NULL)) != 0)
return (err);
/*
@@ -3547,7 +3562,8 @@ again:
if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
recursive, B_TRUE, B_FALSE, recursive, B_FALSE, B_FALSE, B_FALSE,
- B_FALSE, B_TRUE, &local_nv, &local_avl)) != 0)
+ B_FALSE, B_TRUE, B_FALSE, &local_nv, &local_avl,
+ NULL, NULL)) != 0)
return (error);
/*
@@ -4944,7 +4960,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
*cp = '\0';
if (flags->isprefix && !flags->istail && !flags->dryrun &&
- create_parents(hdl, destsnap, strlen(tosnap)) != 0) {
+ create_parents(hdl, destsnap, strlen(tosnap), NULL) != 0) {
err = zfs_error(hdl, EZFS_BADRESTORE, errbuf);
goto out;
}
@@ -5138,7 +5154,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
*cp = '\0';
if (gather_nvlist(hdl, destsnap, NULL, NULL, B_FALSE, B_TRUE,
B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE,
- B_TRUE, &local_nv, &local_avl) == 0) {
+ B_TRUE, B_FALSE, &local_nv, &local_avl,
+ NULL, NULL) == 0) {
*cp = '@';
fs = fsavl_find(local_avl, drrb->drr_toguid, NULL);
fsavl_destroy(local_avl);