]> git.proxmox.com Git - mirror_zfs-debian.git/blobdiff - module/zfs/dmu_object.c
Imported Upstream version 0.6.4.2
[mirror_zfs-debian.git] / module / zfs / dmu_object.c
index b6b82a24bc7f2ccfbf10d633c546d5912557450d..c0e8d7b7fed3aac172316f94993dfd666d76ac4f 100644 (file)
  */
 /*
  * 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>
 #include <sys/dmu_objset.h>
 #include <sys/dmu_tx.h>
 #include <sys/dnode.h>
+#include <sys/zap.h>
+#include <sys/zfeature.h>
 
 uint64_t
 dmu_object_alloc(objset_t *os, dmu_object_type_t ot, int blocksize,
@@ -105,11 +108,9 @@ dmu_object_claim(objset_t *os, uint64_t object, dmu_object_type_t ot,
 
 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)
@@ -120,44 +121,9 @@ dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot,
        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);
 }
 
@@ -196,10 +162,63 @@ dmu_object_next(objset_t *os, uint64_t *objectp, boolean_t hole, uint64_t txg)
        return (error);
 }
 
+/*
+ * Turn this object from old_type into DMU_OTN_ZAP_METADATA, and bump the
+ * refcount on SPA_FEATURE_EXTENSIBLE_DATASET.
+ *
+ * Only for use from syncing context, on MOS objects.
+ */
+void
+dmu_object_zapify(objset_t *mos, uint64_t object, dmu_object_type_t old_type,
+    dmu_tx_t *tx)
+{
+       dnode_t *dn;
+
+       ASSERT(dmu_tx_is_syncing(tx));
+
+       VERIFY0(dnode_hold(mos, object, FTAG, &dn));
+       if (dn->dn_type == DMU_OTN_ZAP_METADATA) {
+               dnode_rele(dn, FTAG);
+               return;
+       }
+       ASSERT3U(dn->dn_type, ==, old_type);
+       ASSERT0(dn->dn_maxblkid);
+       dn->dn_next_type[tx->tx_txg & TXG_MASK] = dn->dn_type =
+           DMU_OTN_ZAP_METADATA;
+       dnode_setdirty(dn, tx);
+       dnode_rele(dn, FTAG);
+
+       mzap_create_impl(mos, object, 0, 0, tx);
+
+       spa_feature_incr(dmu_objset_spa(mos),
+           SPA_FEATURE_EXTENSIBLE_DATASET, tx);
+}
+
+void
+dmu_object_free_zapified(objset_t *mos, uint64_t object, dmu_tx_t *tx)
+{
+       dnode_t *dn;
+       dmu_object_type_t t;
+
+       ASSERT(dmu_tx_is_syncing(tx));
+
+       VERIFY0(dnode_hold(mos, object, FTAG, &dn));
+       t = dn->dn_type;
+       dnode_rele(dn, FTAG);
+
+       if (t == DMU_OTN_ZAP_METADATA) {
+               spa_feature_decr(dmu_objset_spa(mos),
+                   SPA_FEATURE_EXTENSIBLE_DATASET, tx);
+       }
+       VERIFY0(dmu_object_free(mos, object, tx));
+}
+
 #if defined(_KERNEL) && defined(HAVE_SPL)
 EXPORT_SYMBOL(dmu_object_alloc);
 EXPORT_SYMBOL(dmu_object_claim);
 EXPORT_SYMBOL(dmu_object_reclaim);
 EXPORT_SYMBOL(dmu_object_free);
 EXPORT_SYMBOL(dmu_object_next);
+EXPORT_SYMBOL(dmu_object_zapify);
+EXPORT_SYMBOL(dmu_object_free_zapified);
 #endif