Author: delphij
Date: Mon Oct  6 07:29:17 2014
New Revision: 272601
URL: https://svnweb.freebsd.org/changeset/base/272601

Log:
  MFV r272591:
  
  Use loaned ARC buffer for zfs receive to avoid copy.
  
  Illumos issue:
      5162 zfs recv should use loaned arc buffer to avoid copy
  
  MFC after:    2 weeks

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
Directory Properties:
  head/sys/cddl/contrib/opensolaris/   (props changed)

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c   Mon Oct  6 
07:22:48 2014        (r272600)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c   Mon Oct  6 
07:29:17 2014        (r272601)
@@ -1332,7 +1332,14 @@ dmu_assign_arcbuf(dmu_buf_t *handle, uin
        rw_exit(&dn->dn_struct_rwlock);
        DB_DNODE_EXIT(dbuf);
 
-       if (offset == db->db.db_offset && blksz == db->db.db_size) {
+       /*
+        * We can only assign if the offset is aligned, the arc buf is the
+        * same size as the dbuf, and the dbuf is not metadata.  It
+        * can't be metadata because the loaned arc buf comes from the
+        * user-data kmem arena.
+        */
+       if (offset == db->db.db_offset && blksz == db->db.db_size &&
+           DBUF_GET_BUFC_TYPE(db) == ARC_BUFC_DATA) {
                dbuf_assign_arcbuf(db, buf, tx);
                dbuf_rele(db, FTAG);
        } else {

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c      Mon Oct 
 6 07:22:48 2014        (r272600)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c      Mon Oct 
 6 07:29:17 2014        (r272601)
@@ -1273,18 +1273,20 @@ restore_bytes(struct restorearg *ra, voi
 }
 
 static void *
-restore_read(struct restorearg *ra, int len)
+restore_read(struct restorearg *ra, int len, char *buf)
 {
-       void *rv;
        int done = 0;
 
+       if (buf == NULL)
+               buf = ra->buf;
+
        /* some things will require 8-byte alignment, so everything must */
        ASSERT0(len % 8);
 
        while (done < len) {
                ssize_t resid;
 
-               ra->err = restore_bytes(ra, (caddr_t)ra->buf + done,
+               ra->err = restore_bytes(ra, buf + done,
                    len - done, ra->voff, &resid);
 
                if (resid == len - done)
@@ -1296,12 +1298,11 @@ restore_read(struct restorearg *ra, int 
        }
 
        ASSERT3U(done, ==, len);
-       rv = ra->buf;
        if (ra->byteswap)
-               fletcher_4_incremental_byteswap(rv, len, &ra->cksum);
+               fletcher_4_incremental_byteswap(buf, len, &ra->cksum);
        else
-               fletcher_4_incremental_native(rv, len, &ra->cksum);
-       return (rv);
+               fletcher_4_incremental_native(buf, len, &ra->cksum);
+       return (buf);
 }
 
 static void
@@ -1416,7 +1417,7 @@ restore_object(struct restorearg *ra, ob
                return (SET_ERROR(EINVAL));
 
        if (drro->drr_bonuslen) {
-               data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8));
+               data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8), NULL);
                if (ra->err != 0)
                        return (ra->err);
        }
@@ -1513,19 +1514,30 @@ restore_write(struct restorearg *ra, obj
            !DMU_OT_IS_VALID(drrw->drr_type))
                return (SET_ERROR(EINVAL));
 
-       data = restore_read(ra, drrw->drr_length);
-       if (data == NULL)
-               return (ra->err);
-
        if (dmu_object_info(os, drrw->drr_object, NULL) != 0)
                return (SET_ERROR(EINVAL));
 
+       dmu_buf_t *bonus;
+       if (dmu_bonus_hold(os, drrw->drr_object, FTAG, &bonus) != 0)
+               return (SET_ERROR(EINVAL));
+
+       arc_buf_t *abuf = dmu_request_arcbuf(bonus, drrw->drr_length);
+
+       data = restore_read(ra, drrw->drr_length, abuf->b_data);
+       if (data == NULL) {
+               dmu_return_arcbuf(abuf);
+               dmu_buf_rele(bonus, FTAG);
+               return (ra->err);
+       }
+
        tx = dmu_tx_create(os);
 
        dmu_tx_hold_write(tx, drrw->drr_object,
            drrw->drr_offset, drrw->drr_length);
        err = dmu_tx_assign(tx, TXG_WAIT);
        if (err != 0) {
+               dmu_return_arcbuf(abuf);
+               dmu_buf_rele(bonus, FTAG);
                dmu_tx_abort(tx);
                return (err);
        }
@@ -1534,9 +1546,9 @@ restore_write(struct restorearg *ra, obj
                    DMU_OT_BYTESWAP(drrw->drr_type);
                dmu_ot_byteswap[byteswap].ob_func(data, drrw->drr_length);
        }
-       dmu_write(os, drrw->drr_object,
-           drrw->drr_offset, drrw->drr_length, data, tx);
+       dmu_assign_arcbuf(bonus, drrw->drr_offset, abuf, tx);
        dmu_tx_commit(tx);
+       dmu_buf_rele(bonus, FTAG);
        return (0);
 }
 
@@ -1618,7 +1630,7 @@ restore_write_embedded(struct restorearg
        if (drrwnp->drr_compression >= ZIO_COMPRESS_FUNCTIONS)
                return (EINVAL);
 
-       data = restore_read(ra, P2ROUNDUP(drrwnp->drr_psize, 8));
+       data = restore_read(ra, P2ROUNDUP(drrwnp->drr_psize, 8), NULL);
        if (data == NULL)
                return (ra->err);
 
@@ -1653,7 +1665,7 @@ restore_spill(struct restorearg *ra, obj
            drrs->drr_length > SPA_MAXBLOCKSIZE)
                return (SET_ERROR(EINVAL));
 
-       data = restore_read(ra, drrs->drr_length);
+       data = restore_read(ra, drrs->drr_length, NULL);
        if (data == NULL)
                return (ra->err);
 
@@ -1795,7 +1807,7 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, 
         */
        pcksum = ra.cksum;
        while (ra.err == 0 &&
-           NULL != (drr = restore_read(&ra, sizeof (*drr)))) {
+           NULL != (drr = restore_read(&ra, sizeof (*drr), NULL))) {
                if (issig(JUSTLOOKING) && issig(FORREAL)) {
                        ra.err = SET_ERROR(EINTR);
                        goto out;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to