summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-10-03 07:57:32 +0000
committermav <mav@FreeBSD.org>2015-10-03 07:57:32 +0000
commit2c79b8a95c3e6434e650abc47b8b228b7ea1e29b (patch)
tree9244ab7167b51eba90f8278b802be12a3e07f77d /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
parent1bb1f7f370c76640fdbef59f76a68c06b24b304d (diff)
downloadFreeBSD-src-2c79b8a95c3e6434e650abc47b8b228b7ea1e29b.zip
FreeBSD-src-2c79b8a95c3e6434e650abc47b8b228b7ea1e29b.tar.gz
MFC r286683: 5765 add support for estimating send stream size with
lzc_send_space when source is a bookmark Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Christopher Siden <christopher.siden@delphix.com> Reviewed by: Steven Hartland <killing@multiplay.co.uk> Reviewed by: Bayard Bell <buffer.g.overflow@gmail.com> Approved by: Albert Lee <trisk@nexenta.com> Author: Max Grossman <max.grossman@delphix.com> illumos/illumos-gate@643da460c8ca583e39ce053081754e24087f84c8
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c106
1 files changed, 84 insertions, 22 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
index 34d1a99..be1f46d 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
@@ -856,6 +856,40 @@ dmu_send(const char *tosnap, const char *fromsnap,
return (err);
}
+static int
+dmu_adjust_send_estimate_for_indirects(dsl_dataset_t *ds, uint64_t size,
+ uint64_t *sizep)
+{
+ int err;
+ /*
+ * Assume that space (both on-disk and in-stream) is dominated by
+ * data. We will adjust for indirect blocks and the copies property,
+ * but ignore per-object space used (eg, dnodes and DRR_OBJECT records).
+ */
+
+ /*
+ * Subtract out approximate space used by indirect blocks.
+ * Assume most space is used by data blocks (non-indirect, non-dnode).
+ * Assume all blocks are recordsize. Assume ditto blocks and
+ * internal fragmentation counter out compression.
+ *
+ * Therefore, space used by indirect blocks is sizeof(blkptr_t) per
+ * block, which we observe in practice.
+ */
+ uint64_t recordsize;
+ err = dsl_prop_get_int_ds(ds, "recordsize", &recordsize);
+ if (err != 0)
+ return (err);
+ size -= size / recordsize * sizeof (blkptr_t);
+
+ /* Add in the space for the record associated with each block. */
+ size += size / recordsize * sizeof (dmu_replay_record_t);
+
+ *sizep = size;
+
+ return (0);
+}
+
int
dmu_send_estimate(dsl_dataset_t *ds, dsl_dataset_t *fromds, uint64_t *sizep)
{
@@ -891,33 +925,61 @@ dmu_send_estimate(dsl_dataset_t *ds, dsl_dataset_t *fromds, uint64_t *sizep)
return (err);
}
- /*
- * Assume that space (both on-disk and in-stream) is dominated by
- * data. We will adjust for indirect blocks and the copies property,
- * but ignore per-object space used (eg, dnodes and DRR_OBJECT records).
- */
+ err = dmu_adjust_send_estimate_for_indirects(ds, size, sizep);
+ return (err);
+}
+
+/*
+ * Simple callback used to traverse the blocks of a snapshot and sum their
+ * uncompressed size
+ */
+/* ARGSUSED */
+static int
+dmu_calculate_send_traversal(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
+ const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
+{
+ uint64_t *spaceptr = arg;
+ if (bp != NULL && !BP_IS_HOLE(bp)) {
+ *spaceptr += BP_GET_UCSIZE(bp);
+ }
+ return (0);
+}
+
+/*
+ * Given a desination snapshot and a TXG, calculate the approximate size of a
+ * send stream sent from that TXG. from_txg may be zero, indicating that the
+ * whole snapshot will be sent.
+ */
+int
+dmu_send_estimate_from_txg(dsl_dataset_t *ds, uint64_t from_txg,
+ uint64_t *sizep)
+{
+ dsl_pool_t *dp = ds->ds_dir->dd_pool;
+ int err;
+ uint64_t size = 0;
+
+ ASSERT(dsl_pool_config_held(dp));
+
+ /* tosnap must be a snapshot */
+ if (!dsl_dataset_is_snapshot(ds))
+ return (SET_ERROR(EINVAL));
+
+ /* verify that from_txg is before the provided snapshot was taken */
+ if (from_txg >= dsl_dataset_phys(ds)->ds_creation_txg) {
+ return (SET_ERROR(EXDEV));
+ }
/*
- * Subtract out approximate space used by indirect blocks.
- * Assume most space is used by data blocks (non-indirect, non-dnode).
- * Assume all blocks are recordsize. Assume ditto blocks and
- * internal fragmentation counter out compression.
- *
- * Therefore, space used by indirect blocks is sizeof(blkptr_t) per
- * block, which we observe in practice.
+ * traverse the blocks of the snapshot with birth times after
+ * from_txg, summing their uncompressed size
*/
- uint64_t recordsize;
- err = dsl_prop_get_int_ds(ds, "recordsize", &recordsize);
- if (err != 0)
+ err = traverse_dataset(ds, from_txg, TRAVERSE_POST,
+ dmu_calculate_send_traversal, &size);
+ if (err)
return (err);
- size -= size / recordsize * sizeof (blkptr_t);
-
- /* Add in the space for the record associated with each block. */
- size += size / recordsize * sizeof (dmu_replay_record_t);
-
- *sizep = size;
- return (0);
+ err = dmu_adjust_send_estimate_for_indirects(ds, size, sizep);
+ return (err);
}
typedef struct dmu_recv_begin_arg {
OpenPOWER on IntegriCloud