Skip to content

Commit 88904bb

Browse files
ahrensbehlendorf
authored andcommitted
Illumos 5162 - zfs recv should use loaned arc buffer to avoid copy
5162 zfs recv should use loaned arc buffer to avoid copy Reviewed by: Christopher Siden <christopher.siden@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Bayard Bell <Bayard.Bell@nexenta.com> Reviewed by: Richard Elling <richard.elling@gmail.com> Approved by: Garrett D'Amore <garrett@damore.org> References: https://www.illumos.org/issues/5162 illumos/illumos-gate@8a90470 Porting notes: Fix spelling error 's/arena/area/' in dmu.c. In restore_write() declare bonus and abuf at the top of the function. Ported by: Turbo Fredriksson <turbo@bayour.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #2696
1 parent 4b20a6f commit 88904bb

File tree

2 files changed

+38
-18
lines changed

2 files changed

+38
-18
lines changed

module/zfs/dmu.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1387,7 +1387,14 @@ dmu_assign_arcbuf(dmu_buf_t *handle, uint64_t offset, arc_buf_t *buf,
13871387
rw_exit(&dn->dn_struct_rwlock);
13881388
DB_DNODE_EXIT(dbuf);
13891389

1390-
if (offset == db->db.db_offset && blksz == db->db.db_size) {
1390+
/*
1391+
* We can only assign if the offset is aligned, the arc buf is the
1392+
* same size as the dbuf, and the dbuf is not metadata. It
1393+
* can't be metadata because the loaned arc buf comes from the
1394+
* user-data kmem area.
1395+
*/
1396+
if (offset == db->db.db_offset && blksz == db->db.db_size &&
1397+
DBUF_GET_BUFC_TYPE(db) == ARC_BUFC_DATA) {
13911398
dbuf_assign_arcbuf(db, buf, tx);
13921399
dbuf_rele(db, FTAG);
13931400
} else {

module/zfs/dmu_send.c

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,19 +1206,21 @@ free_guid_map_onexit(void *arg)
12061206
}
12071207

12081208
static void *
1209-
restore_read(struct restorearg *ra, int len)
1209+
restore_read(struct restorearg *ra, int len, char *buf)
12101210
{
1211-
void *rv;
12121211
int done = 0;
12131212

1213+
if (buf == NULL)
1214+
buf = ra->buf;
1215+
12141216
/* some things will require 8-byte alignment, so everything must */
12151217
ASSERT0(len % 8);
12161218

12171219
while (done < len) {
12181220
ssize_t resid;
12191221

12201222
ra->err = vn_rdwr(UIO_READ, ra->vp,
1221-
(caddr_t)ra->buf + done, len - done,
1223+
buf + done, len - done,
12221224
ra->voff, UIO_SYSSPACE, FAPPEND,
12231225
RLIM64_INFINITY, CRED(), &resid);
12241226

@@ -1231,12 +1233,11 @@ restore_read(struct restorearg *ra, int len)
12311233
}
12321234

12331235
ASSERT3U(done, ==, len);
1234-
rv = ra->buf;
12351236
if (ra->byteswap)
1236-
fletcher_4_incremental_byteswap(rv, len, &ra->cksum);
1237+
fletcher_4_incremental_byteswap(buf, len, &ra->cksum);
12371238
else
1238-
fletcher_4_incremental_native(rv, len, &ra->cksum);
1239-
return (rv);
1239+
fletcher_4_incremental_native(buf, len, &ra->cksum);
1240+
return (buf);
12401241
}
12411242

12421243
noinline static void
@@ -1367,7 +1368,7 @@ restore_object(struct restorearg *ra, objset_t *os, struct drr_object *drro)
13671368
object = err == 0 ? drro->drr_object : DMU_NEW_OBJECT;
13681369

13691370
if (drro->drr_bonuslen) {
1370-
data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8));
1371+
data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8), NULL);
13711372
if (ra->err != 0)
13721373
return (ra->err);
13731374
}
@@ -1473,26 +1474,38 @@ restore_write(struct restorearg *ra, objset_t *os,
14731474
struct drr_write *drrw)
14741475
{
14751476
dmu_tx_t *tx;
1477+
dmu_buf_t *bonus;
1478+
arc_buf_t *abuf;
14761479
void *data;
14771480
int err;
14781481

14791482
if (drrw->drr_offset + drrw->drr_length < drrw->drr_offset ||
14801483
!DMU_OT_IS_VALID(drrw->drr_type))
14811484
return (SET_ERROR(EINVAL));
14821485

1483-
data = restore_read(ra, drrw->drr_length);
1484-
if (data == NULL)
1485-
return (ra->err);
1486-
14871486
if (dmu_object_info(os, drrw->drr_object, NULL) != 0)
14881487
return (SET_ERROR(EINVAL));
14891488

1489+
if (dmu_bonus_hold(os, drrw->drr_object, FTAG, &bonus) != 0)
1490+
return (SET_ERROR(EINVAL));
1491+
1492+
abuf = dmu_request_arcbuf(bonus, drrw->drr_length);
1493+
1494+
data = restore_read(ra, drrw->drr_length, abuf->b_data);
1495+
if (data == NULL) {
1496+
dmu_return_arcbuf(abuf);
1497+
dmu_buf_rele(bonus, FTAG);
1498+
return (ra->err);
1499+
}
1500+
14901501
tx = dmu_tx_create(os);
14911502

14921503
dmu_tx_hold_write(tx, drrw->drr_object,
14931504
drrw->drr_offset, drrw->drr_length);
14941505
err = dmu_tx_assign(tx, TXG_WAIT);
14951506
if (err != 0) {
1507+
dmu_return_arcbuf(abuf);
1508+
dmu_buf_rele(bonus, FTAG);
14961509
dmu_tx_abort(tx);
14971510
return (err);
14981511
}
@@ -1501,9 +1514,9 @@ restore_write(struct restorearg *ra, objset_t *os,
15011514
DMU_OT_BYTESWAP(drrw->drr_type);
15021515
dmu_ot_byteswap[byteswap].ob_func(data, drrw->drr_length);
15031516
}
1504-
dmu_write(os, drrw->drr_object,
1505-
drrw->drr_offset, drrw->drr_length, data, tx);
1517+
dmu_assign_arcbuf(bonus, drrw->drr_offset, abuf, tx);
15061518
dmu_tx_commit(tx);
1519+
dmu_buf_rele(bonus, FTAG);
15071520
return (0);
15081521
}
15091522

@@ -1585,7 +1598,7 @@ restore_write_embedded(struct restorearg *ra, objset_t *os,
15851598
if (drrwnp->drr_compression >= ZIO_COMPRESS_FUNCTIONS)
15861599
return (EINVAL);
15871600

1588-
data = restore_read(ra, P2ROUNDUP(drrwnp->drr_psize, 8));
1601+
data = restore_read(ra, P2ROUNDUP(drrwnp->drr_psize, 8), NULL);
15891602
if (data == NULL)
15901603
return (ra->err);
15911604

@@ -1620,7 +1633,7 @@ restore_spill(struct restorearg *ra, objset_t *os, struct drr_spill *drrs)
16201633
drrs->drr_length > SPA_MAXBLOCKSIZE)
16211634
return (SET_ERROR(EINVAL));
16221635

1623-
data = restore_read(ra, drrs->drr_length);
1636+
data = restore_read(ra, drrs->drr_length, NULL);
16241637
if (data == NULL)
16251638
return (ra->err);
16261639

@@ -1761,7 +1774,7 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, vnode_t *vp, offset_t *voffp,
17611774
*/
17621775
pcksum = ra.cksum;
17631776
while (ra.err == 0 &&
1764-
NULL != (drr = restore_read(&ra, sizeof (*drr)))) {
1777+
NULL != (drr = restore_read(&ra, sizeof (*drr), NULL))) {
17651778
if (issig(JUSTLOOKING) && issig(FORREAL)) {
17661779
ra.err = SET_ERROR(EINTR);
17671780
goto out;

0 commit comments

Comments
 (0)