summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
diff options
context:
space:
mode:
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.c54
1 files changed, 52 insertions, 2 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 a86814a..f636253 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
@@ -96,6 +96,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;
@@ -162,6 +188,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
@@ -229,6 +264,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
@@ -305,9 +344,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));
@@ -495,6 +534,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);
@@ -1819,3 +1859,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);
+}
OpenPOWER on IntegriCloud