diff options
author | Paul Dagnelie <[email protected]> | 2016-07-07 15:00:51 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2017-06-09 09:46:14 -0700 |
commit | dd429b46b7b8990f48c0276abe8080f626f415cb (patch) | |
tree | ff4a2ac430e73ee8e93b5645179e428971d96ddf /module | |
parent | 38240ebd7a35269e8ce74dc133b34120d707cd6f (diff) |
OpenZFS 8056 - zfs send size estimate is inaccurate for some zvols
Authored by: Paul Dagnelie <[email protected]>
Reviewed by: Matthew Ahrens <[email protected]>
Reviewed by: Pavel Zakharov <[email protected]>
Approved by: Robert Mustacchi <[email protected]>
Reviewed-by: Kash Pande <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: George Melikov <[email protected]>
Ported-by: Giuseppe Di Natale <[email protected]>
The send size estimate for a zvol can be too low, if the size of the
record headers (dmu_replay_record_t's) is a significant portion of the
size. This is typically the case when the data is highly compressible,
especially with embedded blocks.
The problem is that dmu_adjust_send_estimate_for_indirects() assumes
that blocks are the size of the "recordsize" property (128KB). However,
for zvols, the blocks are the size of the "volblocksize" property (8KB).
Therefore, we estimate that there will be 16x less record headers than
there really will be.
The fix is to check the type of the object set (whether it is a zvol or
not) and pick the appropriate property. In addition, while we are at it,
we also add the size of the BEGIN and END records to the estimate.
OpenZFS-issue: https://www.illumos.org/issues/8056
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/faf09cd
Closes #6205
Diffstat (limited to 'module')
-rw-r--r-- | module/zfs/dmu_send.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/module/zfs/dmu_send.c b/module/zfs/dmu_send.c index 03d3f143e..7162355d4 100644 --- a/module/zfs/dmu_send.c +++ b/module/zfs/dmu_send.c @@ -1143,10 +1143,17 @@ dmu_adjust_send_estimate_for_indirects(dsl_dataset_t *ds, uint64_t uncompressed, uint64_t recordsize; uint64_t record_count; + objset_t *os; + VERIFY0(dmu_objset_from_ds(ds, &os)); /* Assume all (uncompressed) blocks are recordsize. */ - err = dsl_prop_get_int_ds(ds, zfs_prop_to_name(ZFS_PROP_RECORDSIZE), - &recordsize); + if (os->os_phys->os_type == DMU_OST_ZVOL) { + err = dsl_prop_get_int_ds(ds, + zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), &recordsize); + } else { + err = dsl_prop_get_int_ds(ds, + zfs_prop_to_name(ZFS_PROP_RECORDSIZE), &recordsize); + } if (err != 0) return (err); record_count = uncompressed / recordsize; @@ -1214,6 +1221,10 @@ dmu_send_estimate(dsl_dataset_t *ds, dsl_dataset_t *fromds, err = dmu_adjust_send_estimate_for_indirects(ds, uncomp, comp, stream_compressed, sizep); + /* + * Add the size of the BEGIN and END records to the estimate. + */ + *sizep += 2 * sizeof (dmu_replay_record_t); return (err); } |