mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-24 03:08:51 +03:00
Illumos #3834
3834 incremental replication of 'holey' file systems is slow Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Approved by: Richard Lowe <richlowe@richlowe.net> References: https://www.illumos.org/issues/3834 illumos/illumos-gate@ca48f36f20 Ported-by: Richard Yao <ryao@gentoo.org> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Issue #1775
This commit is contained in:
committed by
Brian Behlendorf
parent
2883cad5b7
commit
ea97f8ce35
+52
-2
@@ -109,6 +109,32 @@ dump_free(dmu_sendarg_t *dsp, uint64_t object, uint64_t offset,
|
||||
{
|
||||
struct drr_free *drrf = &(dsp->dsa_drr->drr_u.drr_free);
|
||||
|
||||
/*
|
||||
* When we receive a free record, dbuf_free_range() assumes
|
||||
* that the receiving system doesn't have any dbufs in the range
|
||||
* being freed. This is always true because there is a one-record
|
||||
* constraint: we only send one WRITE record for any given
|
||||
* object+offset. We know that the one-record constraint is
|
||||
* true because we always send data in increasing order by
|
||||
* object,offset.
|
||||
*
|
||||
* If the increasing-order constraint ever changes, we should find
|
||||
* another way to assert that the one-record constraint is still
|
||||
* satisfied.
|
||||
*/
|
||||
ASSERT(object > dsp->dsa_last_data_object ||
|
||||
(object == dsp->dsa_last_data_object &&
|
||||
offset > dsp->dsa_last_data_offset));
|
||||
|
||||
/*
|
||||
* If we are doing a non-incremental send, then there can't
|
||||
* be any data in the dataset we're receiving into. Therefore
|
||||
* a free record would simply be a no-op. Save space by not
|
||||
* sending it to begin with.
|
||||
*/
|
||||
if (!dsp->dsa_incremental)
|
||||
return (0);
|
||||
|
||||
if (length != -1ULL && offset + length < offset)
|
||||
length = -1ULL;
|
||||
|
||||
@@ -175,6 +201,15 @@ dump_data(dmu_sendarg_t *dsp, dmu_object_type_t type,
|
||||
{
|
||||
struct drr_write *drrw = &(dsp->dsa_drr->drr_u.drr_write);
|
||||
|
||||
/*
|
||||
* We send data in increasing object, offset order.
|
||||
* See comment in dump_free() for details.
|
||||
*/
|
||||
ASSERT(object > dsp->dsa_last_data_object ||
|
||||
(object == dsp->dsa_last_data_object &&
|
||||
offset > dsp->dsa_last_data_offset));
|
||||
dsp->dsa_last_data_object = object;
|
||||
dsp->dsa_last_data_offset = offset + blksz - 1;
|
||||
|
||||
/*
|
||||
* If there is any kind of pending aggregation (currently either
|
||||
@@ -242,6 +277,10 @@ dump_freeobjects(dmu_sendarg_t *dsp, uint64_t firstobj, uint64_t numobjs)
|
||||
{
|
||||
struct drr_freeobjects *drrfo = &(dsp->dsa_drr->drr_u.drr_freeobjects);
|
||||
|
||||
/* See comment in dump_free(). */
|
||||
if (!dsp->dsa_incremental)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* If there is a pending op, but it's not PENDING_FREEOBJECTS,
|
||||
* push it out, since free block aggregation can only be done for
|
||||
@@ -318,9 +357,9 @@ dump_dnode(dmu_sendarg_t *dsp, uint64_t object, dnode_phys_t *dnp)
|
||||
if (dump_bytes(dsp, DN_BONUS(dnp), P2ROUNDUP(dnp->dn_bonuslen, 8)) != 0)
|
||||
return (SET_ERROR(EINTR));
|
||||
|
||||
/* free anything past the end of the file */
|
||||
/* Free anything past the end of the file. */
|
||||
if (dump_free(dsp, object, (dnp->dn_maxblkid + 1) *
|
||||
(dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT), -1ULL))
|
||||
(dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT), -1ULL) != 0)
|
||||
return (SET_ERROR(EINTR));
|
||||
if (dsp->dsa_err != 0)
|
||||
return (SET_ERROR(EINTR));
|
||||
@@ -503,6 +542,7 @@ dmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *ds,
|
||||
dsp->dsa_toguid = ds->ds_phys->ds_guid;
|
||||
ZIO_SET_CHECKSUM(&dsp->dsa_zc, 0, 0, 0, 0);
|
||||
dsp->dsa_pending_op = PENDING_NONE;
|
||||
dsp->dsa_incremental = (fromtxg != 0);
|
||||
|
||||
mutex_enter(&ds->ds_sendstream_lock);
|
||||
list_insert_head(&ds->ds_sendstreams, dsp);
|
||||
@@ -1799,3 +1839,13 @@ dmu_recv_end(dmu_recv_cookie_t *drc, void *owner)
|
||||
else
|
||||
return (dmu_recv_existing_end(drc));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if this objset is currently being received into.
|
||||
*/
|
||||
boolean_t
|
||||
dmu_objset_is_receiving(objset_t *os)
|
||||
{
|
||||
return (os->os_dsl_dataset != NULL &&
|
||||
os->os_dsl_dataset->ds_owner == dmu_recv_tag);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user