Skip to content

Commit 1152880

Browse files
committed
ZFS send should use spill block prefetched from send_reader_thread
Currently, even though send_reader_thread prefetches spill block, do_dump() will not use it and issues its own blocking arc_read. This causes significant performance degradation when sending datasets with lots of spill blocks. Signed-off-by: Chunwei Chen <[email protected]>
1 parent 6187b19 commit 1152880

File tree

1 file changed

+10
-30
lines changed

1 file changed

+10
-30
lines changed

module/zfs/dmu_send.c

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -939,34 +939,7 @@ do_dump(dmu_send_cookie_t *dscp, struct send_range *range)
939939

940940
ASSERT3U(srdp->datablksz, ==, BP_GET_LSIZE(bp));
941941
ASSERT3U(range->start_blkid + 1, ==, range->end_blkid);
942-
if (BP_GET_TYPE(bp) == DMU_OT_SA) {
943-
arc_flags_t aflags = ARC_FLAG_WAIT;
944-
zio_flag_t zioflags = ZIO_FLAG_CANFAIL;
945-
946-
if (dscp->dsc_featureflags & DMU_BACKUP_FEATURE_RAW) {
947-
ASSERT(BP_IS_PROTECTED(bp));
948-
zioflags |= ZIO_FLAG_RAW;
949-
}
950942

951-
zbookmark_phys_t zb;
952-
ASSERT3U(range->start_blkid, ==, DMU_SPILL_BLKID);
953-
zb.zb_objset = dmu_objset_id(dscp->dsc_os);
954-
zb.zb_object = range->object;
955-
zb.zb_level = 0;
956-
zb.zb_blkid = range->start_blkid;
957-
958-
arc_buf_t *abuf = NULL;
959-
if (!dscp->dsc_dso->dso_dryrun && arc_read(NULL, spa,
960-
bp, arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
961-
zioflags, &aflags, &zb) != 0)
962-
return (SET_ERROR(EIO));
963-
964-
err = dump_spill(dscp, bp, zb.zb_object,
965-
(abuf == NULL ? NULL : abuf->b_data));
966-
if (abuf != NULL)
967-
arc_buf_destroy(abuf, &abuf);
968-
return (err);
969-
}
970943
if (send_do_embed(bp, dscp->dsc_featureflags)) {
971944
err = dump_write_embedded(dscp, range->object,
972945
range->start_blkid * srdp->datablksz,
@@ -975,8 +948,9 @@ do_dump(dmu_send_cookie_t *dscp, struct send_range *range)
975948
}
976949
ASSERT(range->object > dscp->dsc_resume_object ||
977950
(range->object == dscp->dsc_resume_object &&
951+
(range->start_blkid == DMU_SPILL_BLKID ||
978952
range->start_blkid * srdp->datablksz >=
979-
dscp->dsc_resume_offset));
953+
dscp->dsc_resume_offset)));
980954
/* it's a level-0 block of a regular object */
981955

982956
mutex_enter(&srdp->lock);
@@ -1006,8 +980,6 @@ do_dump(dmu_send_cookie_t *dscp, struct send_range *range)
1006980
ASSERT(dscp->dsc_dso->dso_dryrun ||
1007981
srdp->abuf != NULL || srdp->abd != NULL);
1008982

1009-
uint64_t offset = range->start_blkid * srdp->datablksz;
1010-
1011983
char *data = NULL;
1012984
if (srdp->abd != NULL) {
1013985
data = abd_to_buf(srdp->abd);
@@ -1016,6 +988,14 @@ do_dump(dmu_send_cookie_t *dscp, struct send_range *range)
1016988
data = srdp->abuf->b_data;
1017989
}
1018990

991+
if (BP_GET_TYPE(bp) == DMU_OT_SA) {
992+
ASSERT3U(range->start_blkid, ==, DMU_SPILL_BLKID);
993+
err = dump_spill(dscp, bp, range->object, data);
994+
return (err);
995+
}
996+
997+
uint64_t offset = range->start_blkid * srdp->datablksz;
998+
1019999
/*
10201000
* If we have large blocks stored on disk but the send flags
10211001
* don't allow us to send large blocks, we split the data from

0 commit comments

Comments
 (0)