diff options
author | mav <mav@FreeBSD.org> | 2015-10-03 07:57:32 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2015-10-03 07:57:32 +0000 |
commit | 2c79b8a95c3e6434e650abc47b8b228b7ea1e29b (patch) | |
tree | 9244ab7167b51eba90f8278b802be12a3e07f77d /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c | |
parent | 1bb1f7f370c76640fdbef59f76a68c06b24b304d (diff) | |
download | FreeBSD-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.c | 106 |
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 { |