[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2018-01-29 Thread Paul Dagnelie
@pcd1193182 pushed 1 commit.

1decb22  comment, errors


-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/openzfs/openzfs/pull/484/files/8c3bff1cfb34de585bded4d676a5303e44ebaacc..1decb225010a9bc1f14e282853b53426bf15a2af

--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/Tad1f694bf3b89253-M3cecb0aaf8d19941780ba43f
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2018-01-26 Thread Paul Dagnelie
This update rebases on top of openzfs's master branch, as well as the 
encryption PR. The goal is to integrate this change after encryption has 
landed, so I went ahead and did the rebasing early to get it out of the way.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#issuecomment-360884043
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-Mba1d3ac11527e67734ee59fe
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2018-01-26 Thread Paul Dagnelie
pcd1193182 commented on this pull request.



> @@ -2082,6 +2086,38 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
return (err);
 }
 
+/*
+ * Release VOPs and unmount a suspended filesystem.
+ */
+int
+zfs_end_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)

If you're referring to the delphix github, the function is on 5.2: 
https://github.com/delphix/delphix-os/blob/5.2/usr/src/uts/common/fs/zfs/zfs_vfsops.c#L2121
 Not sure why that's relevant, though?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#discussion_r164202251
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-Mfec3fa5fb0987b65e2a098f6
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2018-01-11 Thread Roman Strashkin
Ramzec commented on this pull request.



> @@ -1000,6 +1000,16 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, 
> uint32_t flags)
return;
}
 
+   if (BP_IS_REDACTED(db->db_blkptr)) {

Could you please add a comment, that explains the meaning of this 
condition-block

> +}
+
+static int
+recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds,
+uint64_t fromguid)
+{
+   uint64_t val;
+   int error;
+   dsl_pool_t *dp = ds->ds_dir->dd_pool;
+
+   /* temporary clone name must not exist */
+   error = zap_lookup(dp->dp_meta_objset,
+   dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, recv_clone_name,
+   8, 1, );
+   if (error != ENOENT)
+   return (error == 0 ? EBUSY : error);

return (error == 0 ? SET_ERROR(EBUSY) : error);

> + int error;
+   dsl_pool_t *dp = ds->ds_dir->dd_pool;
+
+   /* temporary clone name must not exist */
+   error = zap_lookup(dp->dp_meta_objset,
+   dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, recv_clone_name,
+   8, 1, );
+   if (error != ENOENT)
+   return (error == 0 ? EBUSY : error);
+
+   /* new snapshot name must not exist */
+   error = zap_lookup(dp->dp_meta_objset,
+   dsl_dataset_phys(ds)->ds_snapnames_zapobj,
+   drba->drba_cookie->drc_tosnap, 8, 1, );
+   if (error != ENOENT)
+   return (error == 0 ? EEXIST : error);

return (error == 0 ? SET_ERROR(EEXIST) : error);

> +
+   /* See comment in restore_write. */
+   save_resume_state(rwa, drrwbr->drr_object, drrwbr->drr_offset, tx);
+   dmu_tx_commit(tx);
+   return (0);
+}
+
+static int
+receive_write_embedded(struct receive_writer_arg *rwa,
+struct drr_write_embedded *drrwe, void *data)
+{
+   dmu_tx_t *tx;
+   int err;
+
+   if (drrwe->drr_offset + drrwe->drr_length < drrwe->drr_offset)
+   return (EINVAL);

SET_ERROR()

> + dmu_tx_commit(tx);
+   return (0);
+}
+
+static int
+receive_write_embedded(struct receive_writer_arg *rwa,
+struct drr_write_embedded *drrwe, void *data)
+{
+   dmu_tx_t *tx;
+   int err;
+
+   if (drrwe->drr_offset + drrwe->drr_length < drrwe->drr_offset)
+   return (EINVAL);
+
+   if (drrwe->drr_psize > BPE_PAYLOAD_SIZE)
+   return (EINVAL);

SET_ERROR()

> +
+static int
+receive_write_embedded(struct receive_writer_arg *rwa,
+struct drr_write_embedded *drrwe, void *data)
+{
+   dmu_tx_t *tx;
+   int err;
+
+   if (drrwe->drr_offset + drrwe->drr_length < drrwe->drr_offset)
+   return (EINVAL);
+
+   if (drrwe->drr_psize > BPE_PAYLOAD_SIZE)
+   return (EINVAL);
+
+   if (drrwe->drr_etype >= NUM_BP_EMBEDDED_TYPES)
+   return (EINVAL);

SET_ERROR()

> +receive_write_embedded(struct receive_writer_arg *rwa,
+struct drr_write_embedded *drrwe, void *data)
+{
+   dmu_tx_t *tx;
+   int err;
+
+   if (drrwe->drr_offset + drrwe->drr_length < drrwe->drr_offset)
+   return (EINVAL);
+
+   if (drrwe->drr_psize > BPE_PAYLOAD_SIZE)
+   return (EINVAL);
+
+   if (drrwe->drr_etype >= NUM_BP_EMBEDDED_TYPES)
+   return (EINVAL);
+   if (drrwe->drr_compression >= ZIO_COMPRESS_FUNCTIONS)
+   return (EINVAL);

SET_ERROR()

> + nvlist_free(nvl);
+   }
+   dsl_redaction_list_rele(rl, FTAG);
+   }
+   }
+}
+
+int
+dsl_get_bookmarks_impl(dsl_dataset_t *ds, nvlist_t *props, nvlist_t *outnvl)
+{
+   dsl_pool_t *dp = ds->ds_dir->dd_pool;
+
+   ASSERT(dsl_pool_config_held(dp));
+
+   if (dsl_dataset_is_snapshot(ds))
+   return (EINVAL);

SET_ERROR()

> @@ -384,6 +862,20 @@ dsl_bookmark_destroy_check(void *arg, dmu_tx_t *tx)
 */
continue;
}
+   if (error == 0 && bm.zbm_redaction_obj != 0) {
+   redaction_list_t *rl = NULL;
+   error = dsl_redaction_list_hold_obj(tx->tx_pool,
+   bm.zbm_redaction_obj, FTAG, );
+   if (error == ENOENT) {
+   error = 0;
+   } else if (error == 0 &&
+   dsl_redaction_list_long_held(rl)) {
+   error = EBUSY;

SET_ERROR()

> + objset_t *mos = rl->rl_mos;
+   redact_block_phys_t *buf;
+   unsigned int bufsize = SPA_OLD_MAXBLOCKSIZE;
+   int err = 0;
+
+   if (rl->rl_phys->rlp_last_object != UINT64_MAX ||
+   rl->rl_phys->rlp_last_blkid != UINT64_MAX) {
+   /*
+* When we finish a send, we update the last object and offset
+* to UINT64_MAX.  If a send fails 

[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2018-01-04 Thread Matthew Ahrens
@Ramzec Thanks for spending the time, we appreciate it.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#issuecomment-35536
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-M624196590fb5f4e496630dd7
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2018-01-04 Thread Roman Strashkin
I'm OK with the changes. I'm going to deeply learn the whole code, to 
understand what is it. Let me several days.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#issuecomment-355358510
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-M2a48a49940e0e547d7004c42
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2018-01-02 Thread Matthew Ahrens
@Ramzec thanks for your review, I know this is a lot of code to look at.  Are 
you happy with @pcd1193182 's responses and the changes made?  If so, we'll 
count you as a code reviewer.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#issuecomment-354874784
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-M4c5a5d8d281aeddd5b073b76
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2017-11-28 Thread Paul Dagnelie
@pcd1193182 pushed 1 commit.

cc8f2f9  ramzec feedback


-- 
You are receiving this because you are subscribed to this thread.
View it on GitHub:
https://github.com/openzfs/openzfs/pull/484/files/2209166b70f40c9842cd61ceb70f8367da8541d6..cc8f2f9b916f736eb2d28866a4b8791b36a82fbf

--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-M3a5cbab2dc96cffe256d7aca
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2017-11-21 Thread Roman Strashkin
Ramzec commented on this pull request.



> + dbn->dbn_dirty = B_FALSE;
+   }
+   }
+#ifdef ZFS_DEBUG
+   for (dsl_bookmark_node_t *dbn = avl_first(>ds_bookmarks);
+   dbn != NULL; dbn = AVL_NEXT(>ds_bookmarks, dbn)) {
+   ASSERT(!dbn->dbn_dirty);
+   }
+#endif
+}
+
+/*
+ * Return the TXG of the most recent bookmark (or 0 if there are no bookmarks).
+ */
+uint64_t
+dsl_bookmark_latest_txg(dsl_dataset_t *ds)

correct, the question about ds_bookmarks, that is used inside of the function.


-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#discussion_r152381447
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-M81b904d3d0b757fbd49f82ea
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2017-11-21 Thread Paul Dagnelie
pcd1193182 commented on this pull request.



> + dbn->dbn_dirty = B_FALSE;
+   }
+   }
+#ifdef ZFS_DEBUG
+   for (dsl_bookmark_node_t *dbn = avl_first(>ds_bookmarks);
+   dbn != NULL; dbn = AVL_NEXT(>ds_bookmarks, dbn)) {
+   ASSERT(!dbn->dbn_dirty);
+   }
+#endif
+}
+
+/*
+ * Return the TXG of the most recent bookmark (or 0 if there are no bookmarks).
+ */
+uint64_t
+dsl_bookmark_latest_txg(dsl_dataset_t *ds)

I'm also a bit confused about this comment; is it a question about how 
ds_bookmarks is protected? Or is it referencing the wrong section of code as 
well?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#discussion_r152379555
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-M1120a80607dd9286f52f2609
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2017-11-21 Thread Roman Strashkin
Ramzec commented on this pull request.



-   return (0);
+   switch (new_type) {
+   case HOLE:
+   pending->sru.hole.datablksz = datablksz;
+   break;
+   case DATA:
+   pending->sru.data.datablksz = datablksz;
+   pending->sru.data.obj_type = dn->dn_type;
+   pending->sru.data.bp = *bp;
+   if (spta->issue_prefetches) {
+   zbookmark_phys_t zb = {0};
+   zb.zb_objset = dmu_objset_id(dn->dn_objset);
+   zb.zb_object = dn->dn_obj

strange

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#discussion_r152377138
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-M0384267ceadda2da5c0f0193
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2017-11-21 Thread Roman Strashkin
Ramzec commented on this pull request.



-   return (0);
+   switch (new_type) {
+   case HOLE:
+   pending->sru.hole.datablksz = datablksz;
+   break;
+   case DATA:
+   pending->sru.data.datablksz = datablksz;
+   pending->sru.data.obj_type = dn->dn_type;
+   pending->sru.data.bp = *bp;
+   if (spta->issue_prefetches) {
+   zbookmark_phys_t zb = {0};
+   zb.zb_objset = dmu_objset_id(dn->dn_objset);
+   zb.zb_object = dn->dn_obj

I meant the following code-block (dmu_send.c line 2127):
+   if (fnvlist_num_pairs(nvl) > 0) {
 +  payload = fnvlist_pack(nvl, _len);
 +  drr->drr_payloadlen = payload_len;
 +  }

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#discussion_r152377585
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-M96e382a40ae719a2ef6bf853
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2017-11-21 Thread Roman Strashkin
Ramzec commented on this pull request.



-   return (0);
+   switch (new_type) {
+   case HOLE:
+   pending->sru.hole.datablksz = datablksz;
+   break;
+   case DATA:
+   pending->sru.data.datablksz = datablksz;
+   pending->sru.data.obj_type = dn->dn_type;
+   pending->sru.data.bp = *bp;
+   if (spta->issue_prefetches) {
+   zbookmark_phys_t zb = {0};
+   zb.zb_objset = dmu_objset_id(dn->dn_objset);
+   zb.zb_object = dn->dn_obj

Just a nit, but there is no reason to walk over the whole nvlist, so 
nvlist_empty() is more logical.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#pullrequestreview-78230004
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-M6c4a821ed69aa72230a8a64f
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2017-11-21 Thread Paul Dagnelie
pcd1193182 commented on this pull request.



-   return (0);
+   switch (new_type) {
+   case HOLE:
+   pending->sru.hole.datablksz = datablksz;
+   break;
+   case DATA:
+   pending->sru.data.datablksz = datablksz;
+   pending->sru.data.obj_type = dn->dn_type;
+   pending->sru.data.bp = *bp;
+   if (spta->issue_prefetches) {
+   zbookmark_phys_t zb = {0};
+   zb.zb_objset = dmu_objset_id(dn->dn_objset);
+   zb.zb_object = dn->dn_obj

I'm a bit confused; how does this comment apply to this code?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#discussion_r152375742
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-Mccb528caebe9f9a9ce1200c2
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2017-11-21 Thread Matthew Ahrens
ahrens commented on this pull request.



> @@ -1054,6 +1054,8 @@ static const char *spa_feature_names[] = {
"com.delphix:embedded_data",
"org.open-zfs:large_blocks",
"org.illumos:sha512",
+   "com.delphix:redaction_bookmarks",

The `redaction_bookmarks` would be active on the sending pool, and 
`redacted_datasets` on the receiving pool.  So you'd typically have only one of 
these features active on a given pool (unless the pool is both a sender and a 
receiver).  This isn't a super strong argument for having different feature 
flags, but hopefully it helps explain why we think about them differently.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#discussion_r152375716
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-M59bcb67f6920fb64d02e73f4
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2017-11-21 Thread Paul Dagnelie
pcd1193182 commented on this pull request.



> + */
+static int
+find_redact_book(libzfs_handle_t *hdl, const char *path,
+const uint64_t *redact_snap_guids, int num_redact_snaps,
+char **bookname)
+{
+   char errbuf[1024];
+   int error = 0;
+   nvlist_t *props = fnvlist_alloc();
+   nvlist_t *bmarks;
+
+   (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
+   "cannot resume send"));
+
+   fnvlist_add_boolean(props, "redact_complete");
+   fnvlist_add_boolean(props, "redact_snaps");

It's normal, in libzfs, to use the literal string value instead of getting it 
with zfs_prop_to_name.  I went with this approach for consistency (and 
compactness, as a fringe benefit), but I don't feel strongly about using it 
instead of getting the name through a function.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#discussion_r152372643
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-M6a3f3010c0a8e508faba14da
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2017-11-21 Thread Paul Dagnelie
pcd1193182 commented on this pull request.



> @@ -1054,6 +1054,8 @@ static const char *spa_feature_names[] = {
"com.delphix:embedded_data",
"org.open-zfs:large_blocks",
"org.illumos:sha512",
+   "com.delphix:redaction_bookmarks",

It's primarily for tracking purposes. By having a featureflag for each one, we 
can easily track whether each feature is active or enabled, which allows pools 
that have had redaction bookmarks (or redacted datasets) added and then deleted 
to be read by older systems.  The two features are also fundamentally 
differently implemented, so it makes sense for them to be tracked separately 
even if they're introduced by the same code to support the same workflow.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/openzfs/openzfs/pull/484#discussion_r152368014
--
openzfs-developer
Archives: 
https://openzfs.topicbox.com/groups/developer/discussions/T1fcfd4fc81bcdfff-M1aecea42b8cb7c30e8099456
Powered by Topicbox: https://topicbox.com


[developer] Re: [openzfs/openzfs] 8741 Implement Redacted Send/Receive (#484)

2017-11-21 Thread Roman Strashkin
Ramzec commented on this pull request.

first look. will try to understand how it works.

> @@ -188,9 +188,13 @@ zfs_iter_bookmarks(zfs_handle_t *zhp, zfs_iter_f func, 
> void *data)
 
/* Setup the requested properties nvlist. */
props = fnvlist_alloc();
-   fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_GUID));
-   fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_CREATETXG));
-   fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_CREATION));
+   for (zfs_prop_t p = 0; p < ZFS_NUM_PROPS; p++) {
+   if (zfs_prop_valid_for_type(p, ZFS_TYPE_BOOKMARK)) {
+   fnvlist_add_boolean(props, zfs_prop_to_name(p));
+   }
+   }
+   fnvlist_add_boolean(props, "redact_snaps");

As I understand "redact_snaps" can be handled by the above loop.

> + */
+static int
+find_redact_book(libzfs_handle_t *hdl, const char *path,
+const uint64_t *redact_snap_guids, int num_redact_snaps,
+char **bookname)
+{
+   char errbuf[1024];
+   int error = 0;
+   nvlist_t *props = fnvlist_alloc();
+   nvlist_t *bmarks;
+
+   (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
+   "cannot resume send"));
+
+   fnvlist_add_boolean(props, "redact_complete");
+   fnvlist_add_boolean(props, "redact_snaps");

zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS) instead of "redact_snaps" ??

> + } else if (error == ENOENT) {
+   zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+   "dataset to be sent no longer exists"));
+   } else {
+   zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+   "unknown error: %s"), strerror(error));
+   }
+   return (zfs_error(hdl, EZFS_BADPROP, errbuf));
+   }
+   nvpair_t *pair;
+   for (pair = nvlist_next_nvpair(bmarks, NULL); pair;
+   pair = nvlist_next_nvpair(bmarks, pair)) {
+
+   nvlist_t *bmark = fnvpair_value_nvlist(pair);
+   nvlist_t *vallist = fnvlist_lookup_nvlist(bmark,
+   "redact_snaps");

zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS) instead of "redact_snaps" ??

> @@ -1644,14 +1878,38 @@ zfs_send_resume(libzfs_handle_t *hdl, sendflags_t 
> *flags, int outfd,
fromname = name;
}
 
-   if (flags->verbose) {
-   uint64_t size = 0;
-   error = lzc_send_space(zhp->zfs_name, fromname,
-   lzc_flags, );
-   if (error == 0)
-   size = MAX(0, (int64_t)(size - bytes));
-   send_print_verbose(stderr, zhp->zfs_name, fromname,
-   size, flags->parsable);
+   redact_snap_guids = NULL;
+
+   if (nvlist_lookup_uint64_array(resume_nvl, "redact_snaps",

zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS) instead of "redact_snaps" ??

> - size = MAX(0, (int64_t)(size - bytes));
-   send_print_verbose(stderr, zhp->zfs_name, fromname,
-   size, flags->parsable);
+   redact_snap_guids = NULL;
+
+   if (nvlist_lookup_uint64_array(resume_nvl, "redact_snaps",
+   _snap_guids, (uint_t *)_redact_snaps) == 0) {
+   char path[ZFS_MAX_DATASET_NAME_LEN];
+
+   (void) strlcpy(path, toname, sizeof (path));
+   char *at = strchr(path, '@');
+   ASSERT3P(at, !=, NULL);
+
+   *at = '\0';
+
+   if ((error = find_redact_book(hdl, path, redact_snap_guids,

It seems "redact_book" will not be freed if "flags->dryrun == B_TRUE"

>  } guid_to_name_data_t;
 
+boolean_t
+redact_snaps_match(zfs_handle_t *zhp, guid_to_name_data_t *gtnd)
+{
+   uint64_t *bmark_snaps;
+   uint_t bmark_num_snaps;
+   nvlist_t *nvl;
+   if (zhp->zfs_type != ZFS_TYPE_BOOKMARK)
+   return (B_FALSE);
+
+   nvl = fnvlist_lookup_nvlist(zhp->zfs_props, "redact_snaps");

zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS) instead of "redact_snaps" ??

> @@ -1054,6 +1054,20 @@ dmu_write_embedded(objset_t *os, uint64_t object, 
> uint64_t offset,
dmu_buf_rele(db, FTAG);
 }
 
+void
+dmu_redact(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
+dmu_tx_t *tx)
+{
+   int numbufs, i;
+   dmu_buf_t **dbp;
+
+   VERIFY(0 == dmu_buf_hold_array(os, object, offset, size, FALSE, FTAG,

VERIFY0()

> +
+   tx = dmu_tx_create(rwa->os);
+
+   dmu_tx_hold_spill(tx, db->db_object);
+
+   err = dmu_tx_assign(tx, TXG_WAIT);
+   if (err != 0) {
+   dmu_buf_rele(db, FTAG);
+   dmu_buf_rele(db_spill, FTAG);
+   dmu_tx_abort(tx);
+   return (err);
+   }
+   dmu_buf_will_dirty(db_spill, tx);
+
+   if (db_spill->db_size < drrs->drr_length)
+   VERIFY(0 == dbuf_spill_set_blksz(db_spill,

VERIFY0

-   return (0);
+   switch (new_type) {
+   case HOLE:
+