Author: delphij
Date: Thu Oct  9 07:52:51 2014
New Revision: 272810
URL: https://svnweb.freebsd.org/changeset/base/272810

Log:
  MFV r272804:
  
  Refactor the code and stop restore_object from creating two transactions.
  
  Illumos issue:
      3693 restore_object uses at least two transactions to restore an object
  
  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_object.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
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   Thu Oct  9 
07:18:40 2014        (r272809)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c   Thu Oct  9 
07:52:51 2014        (r272810)
@@ -1918,6 +1918,7 @@ dmu_object_info_from_dnode(dnode_t *dn, 
        doi->doi_indirection = dn->dn_nlevels;
        doi->doi_checksum = dn->dn_checksum;
        doi->doi_compress = dn->dn_compress;
+       doi->doi_nblkptr = dn->dn_nblkptr;
        doi->doi_physical_blocks_512 = (DN_USED_BYTES(dnp) + 256) >> 9;
        doi->doi_max_offset = (dn->dn_maxblkid + 1) * dn->dn_datablksz;
        doi->doi_fill_count = 0;

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c    Thu Oct 
 9 07:18:40 2014        (r272809)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c    Thu Oct 
 9 07:52:51 2014        (r272810)
@@ -20,7 +20,8 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, 2014 by Delphix. All rights reserved.
+ * Copyright 2014 HybridCluster. All rights reserved.
  */
 
 #include <sys/dmu.h>
@@ -107,11 +108,9 @@ dmu_object_claim(objset_t *os, uint64_t 
 
 int
 dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot,
-    int blocksize, dmu_object_type_t bonustype, int bonuslen)
+    int blocksize, dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
 {
        dnode_t *dn;
-       dmu_tx_t *tx;
-       int nblkptr;
        int err;
 
        if (object == DMU_META_DNODE_OBJECT)
@@ -122,44 +121,9 @@ dmu_object_reclaim(objset_t *os, uint64_
        if (err)
                return (err);
 
-       if (dn->dn_type == ot && dn->dn_datablksz == blocksize &&
-           dn->dn_bonustype == bonustype && dn->dn_bonuslen == bonuslen) {
-               /* nothing is changing, this is a noop */
-               dnode_rele(dn, FTAG);
-               return (0);
-       }
-
-       if (bonustype == DMU_OT_SA) {
-               nblkptr = 1;
-       } else {
-               nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
-       }
-
-       /*
-        * If we are losing blkptrs or changing the block size this must
-        * be a new file instance.   We must clear out the previous file
-        * contents before we can change this type of metadata in the dnode.
-        */
-       if (dn->dn_nblkptr > nblkptr || dn->dn_datablksz != blocksize) {
-               err = dmu_free_long_range(os, object, 0, DMU_OBJECT_END);
-               if (err)
-                       goto out;
-       }
-
-       tx = dmu_tx_create(os);
-       dmu_tx_hold_bonus(tx, object);
-       err = dmu_tx_assign(tx, TXG_WAIT);
-       if (err) {
-               dmu_tx_abort(tx);
-               goto out;
-       }
-
        dnode_reallocate(dn, ot, blocksize, bonustype, bonuslen, tx);
 
-       dmu_tx_commit(tx);
-out:
        dnode_rele(dn, FTAG);
-
        return (err);
 }
 

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      Thu Oct 
 9 07:18:40 2014        (r272809)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c      Thu Oct 
 9 07:52:51 2014        (r272810)
@@ -24,6 +24,7 @@
  * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
  * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  * Copyright (c) 2012, Martin Matuska <m...@freebsd.org>. All rights reserved.
+ * Copyright 2014 HybridCluster. All rights reserved.
  */
 
 #include <sys/dmu.h>
@@ -1392,12 +1393,25 @@ backup_byteswap(dmu_replay_record_t *drr
 #undef DO32
 }
 
+static inline uint8_t
+deduce_nblkptr(dmu_object_type_t bonus_type, uint64_t bonus_size)
+{
+       if (bonus_type == DMU_OT_SA) {
+               return (1);
+       } else {
+               return (1 +
+                   ((DN_MAX_BONUSLEN - bonus_size) >> SPA_BLKPTRSHIFT));
+       }
+}
+
 static int
 restore_object(struct restorearg *ra, objset_t *os, struct drr_object *drro)
 {
-       int err;
+       dmu_object_info_t doi;
        dmu_tx_t *tx;
        void *data = NULL;
+       uint64_t object;
+       int err;
 
        if (drro->drr_type == DMU_OT_NONE ||
            !DMU_OT_IS_VALID(drro->drr_type) ||
@@ -1411,10 +1425,11 @@ restore_object(struct restorearg *ra, ob
                return (SET_ERROR(EINVAL));
        }
 
-       err = dmu_object_info(os, drro->drr_object, NULL);
+       err = dmu_object_info(os, drro->drr_object, &doi);
 
        if (err != 0 && err != ENOENT)
                return (SET_ERROR(EINVAL));
+       object = err == 0 ? drro->drr_object : DMU_NEW_OBJECT;
 
        if (drro->drr_bonuslen) {
                data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8), NULL);
@@ -1422,37 +1437,53 @@ restore_object(struct restorearg *ra, ob
                        return (ra->err);
        }
 
-       if (err == ENOENT) {
-               /* currently free, want to be allocated */
-               tx = dmu_tx_create(os);
-               dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
-               err = dmu_tx_assign(tx, TXG_WAIT);
-               if (err != 0) {
-                       dmu_tx_abort(tx);
-                       return (err);
+       /*
+        * If we are losing blkptrs or changing the block size this must
+        * be a new file instance.  We must clear out the previous file
+        * contents before we can change this type of metadata in the dnode.
+        */
+       if (err == 0) {
+               int nblkptr;
+
+               nblkptr = deduce_nblkptr(drro->drr_bonustype,
+                   drro->drr_bonuslen);
+
+               if (drro->drr_blksz != doi.doi_data_block_size ||
+                   nblkptr < doi.doi_nblkptr) {
+                       err = dmu_free_long_range(os, drro->drr_object,
+                           0, DMU_OBJECT_END);
+                       if (err != 0)
+                               return (SET_ERROR(EINVAL));
                }
+       }
+
+       tx = dmu_tx_create(os);
+       dmu_tx_hold_bonus(tx, object);
+       err = dmu_tx_assign(tx, TXG_WAIT);
+       if (err != 0) {
+               dmu_tx_abort(tx);
+               return (err);
+       }
+
+       if (object == DMU_NEW_OBJECT) {
+               /* currently free, want to be allocated */
                err = dmu_object_claim(os, drro->drr_object,
                    drro->drr_type, drro->drr_blksz,
                    drro->drr_bonustype, drro->drr_bonuslen, tx);
-               dmu_tx_commit(tx);
-       } else {
-               /* currently allocated, want to be allocated */
+       } else if (drro->drr_type != doi.doi_type ||
+           drro->drr_blksz != doi.doi_data_block_size ||
+           drro->drr_bonustype != doi.doi_bonus_type ||
+           drro->drr_bonuslen != doi.doi_bonus_size) {
+               /* currently allocated, but with different properties */
                err = dmu_object_reclaim(os, drro->drr_object,
                    drro->drr_type, drro->drr_blksz,
-                   drro->drr_bonustype, drro->drr_bonuslen);
+                   drro->drr_bonustype, drro->drr_bonuslen, tx);
        }
        if (err != 0) {
+               dmu_tx_commit(tx);
                return (SET_ERROR(EINVAL));
        }
 
-       tx = dmu_tx_create(os);
-       dmu_tx_hold_bonus(tx, drro->drr_object);
-       err = dmu_tx_assign(tx, TXG_WAIT);
-       if (err != 0) {
-               dmu_tx_abort(tx);
-               return (err);
-       }
-
        dmu_object_set_checksum(os, drro->drr_object, drro->drr_checksumtype,
            tx);
        dmu_object_set_compress(os, drro->drr_object, drro->drr_compress, tx);

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h       Thu Oct 
 9 07:18:40 2014        (r272809)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h       Thu Oct 
 9 07:52:51 2014        (r272810)
@@ -25,6 +25,7 @@
  * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  * Copyright 2013 DEY Storage Systems, Inc.
+ * Copyright 2014 HybridCluster. All rights reserved.
  */
 
 /* Portions Copyright 2010 Robert Milkowski */
@@ -341,7 +342,7 @@ uint64_t dmu_object_alloc(objset_t *os, 
 int dmu_object_claim(objset_t *os, uint64_t object, dmu_object_type_t ot,
     int blocksize, dmu_object_type_t bonus_type, int bonus_len, dmu_tx_t *tx);
 int dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot,
-    int blocksize, dmu_object_type_t bonustype, int bonuslen);
+    int blocksize, dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *txp);
 
 /*
  * Free an object from this objset.
@@ -662,7 +663,8 @@ typedef struct dmu_object_info {
        uint8_t doi_indirection;                /* 2 = dnode->indirect->data */
        uint8_t doi_checksum;
        uint8_t doi_compress;
-       uint8_t doi_pad[5];
+       uint8_t doi_nblkptr;
+       uint8_t doi_pad[4];
        uint64_t doi_physical_blocks_512;       /* data + metadata, 512b blks */
        uint64_t doi_max_offset;
        uint64_t doi_fill_count;                /* number of non-empty blocks */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to