Fix synchronicity for ZVOLs.
[zfs.git] / module / zfs / dmu_tx.c
index 5fc062c..fa64b3a 100644 (file)
@@ -186,7 +186,7 @@ dmu_tx_count_twig(dmu_tx_hold_t *txh, dnode_t *dn, dmu_buf_impl_t *db,
                ASSERT(level != 0);
                db = NULL;
        } else {
-               ASSERT(db->db_dnode == dn);
+               ASSERT(DB_DNODE(db) == dn);
                ASSERT(db->db_level == level);
                ASSERT(db->db.db_size == space);
                ASSERT(db->db_blkid == blkid);
@@ -216,6 +216,7 @@ dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
        uint64_t start, end, i;
        int min_bs, max_bs, min_ibs, max_ibs, epbs, bits;
        int err = 0;
+       int l;
 
        if (len == 0)
                return;
@@ -303,7 +304,7 @@ dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
                 * we need to account for overwrites/unref.
                 */
                if (start <= dn->dn_maxblkid) {
-                       for (int l = 0; l < DN_MAX_LEVELS; l++)
+                       for (l = 0; l < DN_MAX_LEVELS; l++)
                                history[l] = -1ULL;
                }
                while (start <= dn->dn_maxblkid) {
@@ -384,7 +385,7 @@ static void
 dmu_tx_count_dnode(dmu_tx_hold_t *txh)
 {
        dnode_t *dn = txh->txh_dnode;
-       dnode_t *mdn = txh->txh_tx->tx_objset->os_meta_dnode;
+       dnode_t *mdn = DMU_META_DNODE(txh->txh_tx->tx_objset);
        uint64_t space = mdn->dn_datablksz +
            ((mdn->dn_nlevels-1) << mdn->dn_indblkshift);
 
@@ -787,18 +788,24 @@ dmu_tx_dirty_buf(dmu_tx_t *tx, dmu_buf_impl_t *db)
 {
        dmu_tx_hold_t *txh;
        int match_object = FALSE, match_offset = FALSE;
-       dnode_t *dn = db->db_dnode;
+       dnode_t *dn;
 
+       DB_DNODE_ENTER(db);
+       dn = DB_DNODE(db);
        ASSERT(tx->tx_txg != 0);
        ASSERT(tx->tx_objset == NULL || dn->dn_objset == tx->tx_objset);
        ASSERT3U(dn->dn_object, ==, db->db.db_object);
 
-       if (tx->tx_anyobj)
+       if (tx->tx_anyobj) {
+               DB_DNODE_EXIT(db);
                return;
+       }
 
        /* XXX No checking on the meta dnode for now */
-       if (db->db.db_object == DMU_META_DNODE_OBJECT)
+       if (db->db.db_object == DMU_META_DNODE_OBJECT) {
+               DB_DNODE_EXIT(db);
                return;
+       }
 
        for (txh = list_head(&tx->tx_holds); txh;
            txh = list_next(&tx->tx_holds, txh)) {
@@ -870,9 +877,12 @@ dmu_tx_dirty_buf(dmu_tx_t *tx, dmu_buf_impl_t *db)
                                ASSERT(!"bad txh_type");
                        }
                }
-               if (match_object && match_offset)
+               if (match_object && match_offset) {
+                       DB_DNODE_EXIT(db);
                        return;
+               }
        }
+       DB_DNODE_EXIT(db);
        panic("dirtying dbuf obj=%llx lvl=%u blkid=%llx but not tx_held\n",
            (u_longlong_t)db->db.db_object, db->db_level,
            (u_longlong_t)db->db_blkid);
@@ -1115,7 +1125,7 @@ dmu_tx_commit(dmu_tx_t *tx)
 
        ASSERT(tx->tx_txg != 0);
 
-       while (txh = list_head(&tx->tx_holds)) {
+       while ((txh = list_head(&tx->tx_holds))) {
                dnode_t *dn = txh->txh_dnode;
 
                list_remove(&tx->tx_holds, txh);
@@ -1163,7 +1173,7 @@ dmu_tx_abort(dmu_tx_t *tx)
 
        ASSERT(tx->tx_txg == 0);
 
-       while (txh = list_head(&tx->tx_holds)) {
+       while ((txh = list_head(&tx->tx_holds))) {
                dnode_t *dn = txh->txh_dnode;
 
                list_remove(&tx->tx_holds, txh);
@@ -1217,7 +1227,7 @@ dmu_tx_do_callbacks(list_t *cb_list, int error)
 {
        dmu_tx_callback_t *dcb;
 
-       while (dcb = list_head(cb_list)) {
+       while ((dcb = list_head(cb_list))) {
                list_remove(cb_list, dcb);
                dcb->dcb_func(dcb->dcb_data, error);
                kmem_free(dcb, sizeof (dmu_tx_callback_t));
@@ -1355,9 +1365,37 @@ dmu_tx_hold_sa(dmu_tx_t *tx, sa_handle_t *hdl, boolean_t may_grow)
        if (may_grow && tx->tx_objset->os_sa->sa_layout_attr_obj)
                dmu_tx_hold_zap(tx, sa->sa_layout_attr_obj, B_TRUE, NULL);
 
-       if (sa->sa_force_spill || may_grow || hdl->sa_spill ||
-           ((dmu_buf_impl_t *)hdl->sa_bonus)->db_dnode->dn_have_spill) {
+       if (sa->sa_force_spill || may_grow || hdl->sa_spill) {
                ASSERT(tx->tx_txg == 0);
                dmu_tx_hold_spill(tx, object);
+       } else {
+               dmu_buf_impl_t *db = (dmu_buf_impl_t *)hdl->sa_bonus;
+               dnode_t *dn;
+
+               DB_DNODE_ENTER(db);
+               dn = DB_DNODE(db);
+               if (dn->dn_have_spill) {
+                       ASSERT(tx->tx_txg == 0);
+                       dmu_tx_hold_spill(tx, object);
+               }
+               DB_DNODE_EXIT(db);
        }
 }
+
+#if defined(_KERNEL) && defined(HAVE_SPL)
+EXPORT_SYMBOL(dmu_tx_create);
+EXPORT_SYMBOL(dmu_tx_hold_write);
+EXPORT_SYMBOL(dmu_tx_hold_free);
+EXPORT_SYMBOL(dmu_tx_hold_zap);
+EXPORT_SYMBOL(dmu_tx_hold_bonus);
+EXPORT_SYMBOL(dmu_tx_abort);
+EXPORT_SYMBOL(dmu_tx_assign);
+EXPORT_SYMBOL(dmu_tx_wait);
+EXPORT_SYMBOL(dmu_tx_commit);
+EXPORT_SYMBOL(dmu_tx_get_txg);
+EXPORT_SYMBOL(dmu_tx_callback_register);
+EXPORT_SYMBOL(dmu_tx_do_callbacks);
+EXPORT_SYMBOL(dmu_tx_hold_spill);
+EXPORT_SYMBOL(dmu_tx_hold_sa_create);
+EXPORT_SYMBOL(dmu_tx_hold_sa);
+#endif