]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/zap_micro.c
Provide more flexible object allocation interface
[mirror_zfs.git] / module / zfs / zap_micro.c
index a628cb881b2ee95b685c1d680bfdbd1cd31e8283..fa369f7975484a13372c6fc776663efa5f4dd873 100644 (file)
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
  * Copyright 2017 Nexenta Systems, Inc.
  */
@@ -501,6 +501,10 @@ handle_winner:
        return (winner);
 }
 
+/*
+ * This routine "consumes" the caller's hold on the dbuf, which must
+ * have the specified tag.
+ */
 static int
 zap_lockdir_impl(dmu_buf_t *db, void *tag, dmu_tx_t *tx,
     krw_t lti, boolean_t fatreader, boolean_t adding, zap_t **zapp)
@@ -586,6 +590,14 @@ zap_lockdir_by_dnode(dnode_t *dn, dmu_tx_t *tx,
        if (err != 0) {
                return (err);
        }
+#ifdef ZFS_DEBUG
+       {
+               dmu_object_info_t doi;
+               dmu_object_info_from_db(db, &doi);
+               ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP);
+       }
+#endif
+
        err = zap_lockdir_impl(db, tag, tx, lti, fatreader, adding, zapp);
        if (err != 0) {
                dmu_buf_rele(db, tag);
@@ -602,6 +614,13 @@ zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx,
        int err = dmu_buf_hold(os, obj, 0, tag, &db, DMU_READ_NO_PREFETCH);
        if (err != 0)
                return (err);
+#ifdef ZFS_DEBUG
+       {
+               dmu_object_info_t doi;
+               dmu_object_info_from_db(db, &doi);
+               ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP);
+       }
+#endif
        err = zap_lockdir_impl(db, tag, tx, lti, fatreader, adding, zapp);
        if (err != 0)
                dmu_buf_rele(db, tag);
@@ -680,38 +699,58 @@ mzap_upgrade(zap_t **zapp, void *tag, dmu_tx_t *tx, zap_flags_t flags)
  * of them may be supplied.
  */
 void
-mzap_create_impl(objset_t *os, uint64_t obj, int normflags, zap_flags_t flags,
-    dmu_tx_t *tx)
+mzap_create_impl(dnode_t *dn, int normflags, zap_flags_t flags, dmu_tx_t *tx)
 {
        dmu_buf_t *db;
 
-       VERIFY0(dmu_buf_hold(os, obj, 0, FTAG, &db, DMU_READ_NO_PREFETCH));
-
-#ifdef ZFS_DEBUG
-       {
-               dmu_object_info_t doi;
-               dmu_object_info_from_db(db, &doi);
-               ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP);
-       }
-#endif
+       VERIFY0(dmu_buf_hold_by_dnode(dn, 0, FTAG, &db, DMU_READ_NO_PREFETCH));
 
        dmu_buf_will_dirty(db, tx);
        mzap_phys_t *zp = db->db_data;
        zp->mz_block_type = ZBT_MICRO;
-       zp->mz_salt = ((uintptr_t)db ^ (uintptr_t)tx ^ (obj << 1)) | 1ULL;
+       zp->mz_salt =
+           ((uintptr_t)db ^ (uintptr_t)tx ^ (dn->dn_object << 1)) | 1ULL;
        zp->mz_normflags = normflags;
-       dmu_buf_rele(db, FTAG);
 
        if (flags != 0) {
                zap_t *zap;
                /* Only fat zap supports flags; upgrade immediately. */
-               VERIFY(0 == zap_lockdir(os, obj, tx, RW_WRITER,
-                   B_FALSE, B_FALSE, FTAG, &zap));
+               VERIFY0(zap_lockdir_impl(db, FTAG, tx, RW_WRITER,
+                   B_FALSE, B_FALSE, &zap));
                VERIFY0(mzap_upgrade(&zap, FTAG, tx, flags));
                zap_unlockdir(zap, FTAG);
+       } else {
+               dmu_buf_rele(db, FTAG);
        }
 }
 
+static uint64_t
+zap_create_impl(objset_t *os, int normflags, zap_flags_t flags,
+    dmu_object_type_t ot, int leaf_blockshift, int indirect_blockshift,
+    dmu_object_type_t bonustype, int bonuslen, int dnodesize,
+    dnode_t **allocated_dnode, void *tag, dmu_tx_t *tx)
+{
+       uint64_t obj;
+
+       ASSERT3U(DMU_OT_BYTESWAP(ot), ==, DMU_BSWAP_ZAP);
+
+       if (allocated_dnode == NULL) {
+               dnode_t *dn;
+               obj = dmu_object_alloc_hold(os, ot, 1ULL << leaf_blockshift,
+                   indirect_blockshift, bonustype, bonuslen, dnodesize,
+                   &dn, FTAG, tx);
+               mzap_create_impl(dn, normflags, flags, tx);
+               dnode_rele(dn, FTAG);
+       } else {
+               obj = dmu_object_alloc_hold(os, ot, 1ULL << leaf_blockshift,
+                   indirect_blockshift, bonustype, bonuslen, dnodesize,
+                   allocated_dnode, tag, tx);
+               mzap_create_impl(*allocated_dnode, normflags, flags, tx);
+       }
+
+       return (obj);
+}
+
 int
 zap_create_claim(objset_t *os, uint64_t obj, dmu_object_type_t ot,
     dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
@@ -742,11 +781,23 @@ zap_create_claim_norm_dnsize(objset_t *os, uint64_t obj, int normflags,
     dmu_object_type_t ot, dmu_object_type_t bonustype, int bonuslen,
     int dnodesize, dmu_tx_t *tx)
 {
-       int err = dmu_object_claim_dnsize(os, obj, ot, 0, bonustype, bonuslen,
+       dnode_t *dn;
+       int error;
+
+       ASSERT3U(DMU_OT_BYTESWAP(ot), ==, DMU_BSWAP_ZAP);
+       error = dmu_object_claim_dnsize(os, obj, ot, 0, bonustype, bonuslen,
            dnodesize, tx);
-       if (err != 0)
-               return (err);
-       mzap_create_impl(os, obj, normflags, 0, tx);
+       if (error != 0)
+               return (error);
+
+       error = dnode_hold(os, obj, FTAG, &dn);
+       if (error != 0)
+               return (error);
+
+       mzap_create_impl(dn, normflags, 0, tx);
+
+       dnode_rele(dn, FTAG);
+
        return (0);
 }
 
@@ -777,11 +828,8 @@ uint64_t
 zap_create_norm_dnsize(objset_t *os, int normflags, dmu_object_type_t ot,
     dmu_object_type_t bonustype, int bonuslen, int dnodesize, dmu_tx_t *tx)
 {
-       uint64_t obj = dmu_object_alloc_dnsize(os, ot, 0, bonustype, bonuslen,
-           dnodesize, tx);
-
-       mzap_create_impl(os, obj, normflags, 0, tx);
-       return (obj);
+       return (zap_create_impl(os, normflags, 0, ot, 0, 0,
+           bonustype, bonuslen, dnodesize, NULL, NULL, tx));
 }
 
 uint64_t
@@ -798,19 +846,25 @@ zap_create_flags_dnsize(objset_t *os, int normflags, zap_flags_t flags,
     dmu_object_type_t ot, int leaf_blockshift, int indirect_blockshift,
     dmu_object_type_t bonustype, int bonuslen, int dnodesize, dmu_tx_t *tx)
 {
-       uint64_t obj = dmu_object_alloc_dnsize(os, ot, 0, bonustype, bonuslen,
-           dnodesize, tx);
-
-       ASSERT(leaf_blockshift >= SPA_MINBLOCKSHIFT &&
-           leaf_blockshift <= SPA_OLD_MAXBLOCKSHIFT &&
-           indirect_blockshift >= SPA_MINBLOCKSHIFT &&
-           indirect_blockshift <= SPA_OLD_MAXBLOCKSHIFT);
-
-       VERIFY(dmu_object_set_blocksize(os, obj,
-           1ULL << leaf_blockshift, indirect_blockshift, tx) == 0);
+       return (zap_create_impl(os, normflags, flags, ot, leaf_blockshift,
+           indirect_blockshift, bonustype, bonuslen, dnodesize, NULL, NULL,
+           tx));
+}
 
-       mzap_create_impl(os, obj, normflags, flags, tx);
-       return (obj);
+/*
+ * Create a zap object and return a pointer to the newly allocated dnode via
+ * the allocated_dnode argument.  The returned dnode will be held and the
+ * caller is responsible for releasing the hold by calling dnode_rele().
+ */
+uint64_t
+zap_create_hold(objset_t *os, int normflags, zap_flags_t flags,
+    dmu_object_type_t ot, int leaf_blockshift, int indirect_blockshift,
+    dmu_object_type_t bonustype, int bonuslen, int dnodesize,
+    dnode_t **allocated_dnode, void *tag, dmu_tx_t *tx)
+{
+       return (zap_create_impl(os, normflags, flags, ot, leaf_blockshift,
+           indirect_blockshift, bonustype, bonuslen, dnodesize,
+           allocated_dnode, tag, tx));
 }
 
 int
@@ -1268,19 +1322,8 @@ zap_update(objset_t *os, uint64_t zapobj, const char *name,
     int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx)
 {
        zap_t *zap;
-       ASSERTV(uint64_t oldval);
        const uint64_t *intval = val;
 
-#ifdef ZFS_DEBUG
-
-       /*
-        * If there is an old value, it shouldn't change across the
-        * lockdir (eg, due to bprewrite's xlation).
-        */
-       if (integer_size == 8 && num_integers == 1)
-               (void) zap_lookup(os, zapobj, name, 8, 1, &oldval);
-#endif
-
        int err =
            zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
        if (err != 0)
@@ -1307,7 +1350,6 @@ zap_update(objset_t *os, uint64_t zapobj, const char *name,
        } else {
                mzap_ent_t *mze = mze_find(zn);
                if (mze != NULL) {
-                       ASSERT3U(MZE_PHYS(zap, mze)->mze_value, ==, oldval);
                        MZE_PHYS(zap, mze)->mze_value = *intval;
                } else {
                        mzap_addent(zn, *intval);
@@ -1593,6 +1635,7 @@ EXPORT_SYMBOL(zap_create_flags_dnsize);
 EXPORT_SYMBOL(zap_create_claim);
 EXPORT_SYMBOL(zap_create_claim_norm);
 EXPORT_SYMBOL(zap_create_claim_norm_dnsize);
+EXPORT_SYMBOL(zap_create_hold);
 EXPORT_SYMBOL(zap_destroy);
 EXPORT_SYMBOL(zap_lookup);
 EXPORT_SYMBOL(zap_lookup_by_dnode);