mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 18:40:43 +03:00
Illumos 5765 - add support for estimating send stream size with lzc_send_space when source is a bookmark
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> References: https://www.illumos.org/issues/5765 https://github.com/illumos/illumos-gate/commit/643da460 Porting notes: * Unused variable 'recordsize' in dmu_send_estimate() dropped Ported-by: DHE <git@dehacked.net> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #3397
This commit is contained in:
committed by
Brian Behlendorf
parent
19b3b1d2a2
commit
5dc8b7365f
+87
-25
@@ -836,11 +836,45 @@ 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)
|
||||
{
|
||||
int err;
|
||||
uint64_t size, recordsize;
|
||||
uint64_t size;
|
||||
ASSERTV(dsl_pool_t *dp = ds->ds_dir->dd_pool);
|
||||
|
||||
ASSERT(dsl_pool_config_held(dp));
|
||||
@@ -867,34 +901,62 @@ 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).
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
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));
|
||||
}
|
||||
/*
|
||||
* traverse the blocks of the snapshot with birth times after
|
||||
* from_txg, summing their uncompressed size
|
||||
*/
|
||||
err = traverse_dataset(ds, from_txg, TRAVERSE_POST,
|
||||
dmu_calculate_send_traversal, &size);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
err = dmu_adjust_send_estimate_for_indirects(ds, size, sizep);
|
||||
return (err);
|
||||
}
|
||||
|
||||
typedef struct dmu_recv_begin_arg {
|
||||
const char *drba_origin;
|
||||
dmu_recv_cookie_t *drba_cookie;
|
||||
|
||||
Reference in New Issue
Block a user