@@ -109,6 +109,32 @@ dump_free(dmu_sendarg_t *dsp, uint64_t object, uint64_t offset,
109
109
{
110
110
struct drr_free * drrf = & (dsp -> dsa_drr -> drr_u .drr_free );
111
111
112
+ /*
113
+ * When we receive a free record, dbuf_free_range() assumes
114
+ * that the receiving system doesn't have any dbufs in the range
115
+ * being freed. This is always true because there is a one-record
116
+ * constraint: we only send one WRITE record for any given
117
+ * object+offset. We know that the one-record constraint is
118
+ * true because we always send data in increasing order by
119
+ * object,offset.
120
+ *
121
+ * If the increasing-order constraint ever changes, we should find
122
+ * another way to assert that the one-record constraint is still
123
+ * satisfied.
124
+ */
125
+ ASSERT (object > dsp -> dsa_last_data_object ||
126
+ (object == dsp -> dsa_last_data_object &&
127
+ offset > dsp -> dsa_last_data_offset ));
128
+
129
+ /*
130
+ * If we are doing a non-incremental send, then there can't
131
+ * be any data in the dataset we're receiving into. Therefore
132
+ * a free record would simply be a no-op. Save space by not
133
+ * sending it to begin with.
134
+ */
135
+ if (!dsp -> dsa_incremental )
136
+ return (0 );
137
+
112
138
if (length != -1ULL && offset + length < offset )
113
139
length = -1ULL ;
114
140
@@ -175,6 +201,15 @@ dump_data(dmu_sendarg_t *dsp, dmu_object_type_t type,
175
201
{
176
202
struct drr_write * drrw = & (dsp -> dsa_drr -> drr_u .drr_write );
177
203
204
+ /*
205
+ * We send data in increasing object, offset order.
206
+ * See comment in dump_free() for details.
207
+ */
208
+ ASSERT (object > dsp -> dsa_last_data_object ||
209
+ (object == dsp -> dsa_last_data_object &&
210
+ offset > dsp -> dsa_last_data_offset ));
211
+ dsp -> dsa_last_data_object = object ;
212
+ dsp -> dsa_last_data_offset = offset + blksz - 1 ;
178
213
179
214
/*
180
215
* 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)
242
277
{
243
278
struct drr_freeobjects * drrfo = & (dsp -> dsa_drr -> drr_u .drr_freeobjects );
244
279
280
+ /* See comment in dump_free(). */
281
+ if (!dsp -> dsa_incremental )
282
+ return (0 );
283
+
245
284
/*
246
285
* If there is a pending op, but it's not PENDING_FREEOBJECTS,
247
286
* 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)
318
357
if (dump_bytes (dsp , DN_BONUS (dnp ), P2ROUNDUP (dnp -> dn_bonuslen , 8 )) != 0 )
319
358
return (SET_ERROR (EINTR ));
320
359
321
- /* free anything past the end of the file */
360
+ /* Free anything past the end of the file. */
322
361
if (dump_free (dsp , object , (dnp -> dn_maxblkid + 1 ) *
323
- (dnp -> dn_datablkszsec << SPA_MINBLOCKSHIFT ), -1ULL ))
362
+ (dnp -> dn_datablkszsec << SPA_MINBLOCKSHIFT ), -1ULL ) != 0 )
324
363
return (SET_ERROR (EINTR ));
325
364
if (dsp -> dsa_err != 0 )
326
365
return (SET_ERROR (EINTR ));
@@ -503,6 +542,7 @@ dmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *ds,
503
542
dsp -> dsa_toguid = ds -> ds_phys -> ds_guid ;
504
543
ZIO_SET_CHECKSUM (& dsp -> dsa_zc , 0 , 0 , 0 , 0 );
505
544
dsp -> dsa_pending_op = PENDING_NONE ;
545
+ dsp -> dsa_incremental = (fromtxg != 0 );
506
546
507
547
mutex_enter (& ds -> ds_sendstream_lock );
508
548
list_insert_head (& ds -> ds_sendstreams , dsp );
@@ -1799,3 +1839,13 @@ dmu_recv_end(dmu_recv_cookie_t *drc, void *owner)
1799
1839
else
1800
1840
return (dmu_recv_existing_end (drc ));
1801
1841
}
1842
+
1843
+ /*
1844
+ * Return TRUE if this objset is currently being received into.
1845
+ */
1846
+ boolean_t
1847
+ dmu_objset_is_receiving (objset_t * os )
1848
+ {
1849
+ return (os -> os_dsl_dataset != NULL &&
1850
+ os -> os_dsl_dataset -> ds_owner == dmu_recv_tag );
1851
+ }
0 commit comments