dmu_tx: Fix possible NULL pointer dereference
[zfs.git] / module / zfs / dmu_tx.c
index e47d858..fd71413 100644 (file)
@@ -21,7 +21,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 #include <sys/dmu.h>
@@ -301,6 +301,7 @@ dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
                        delta = P2NPHASE(off, dn->dn_datablksz);
                }
 
+               min_ibs = max_ibs = dn->dn_indblkshift;
                if (dn->dn_maxblkid > 0) {
                        /*
                         * The blocksize can't change,
@@ -308,13 +309,6 @@ dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
                         */
                        ASSERT(dn->dn_datablkshift != 0);
                        min_bs = max_bs = dn->dn_datablkshift;
-                       min_ibs = max_ibs = dn->dn_indblkshift;
-               } else if (dn->dn_indblkshift > max_ibs) {
-                       /*
-                        * This ensures that if we reduce DN_MAX_INDBLKSHIFT,
-                        * the code will still work correctly on older pools.
-                        */
-                       min_ibs = max_ibs = dn->dn_indblkshift;
                }
 
                /*
@@ -779,12 +773,13 @@ void
 dmu_tx_hold_space(dmu_tx_t *tx, uint64_t space)
 {
        dmu_tx_hold_t *txh;
+
        ASSERT(tx->tx_txg == 0);
 
        txh = dmu_tx_hold_object_impl(tx, tx->tx_objset,
            DMU_NEW_OBJECT, THT_SPACE, space, 0);
-
-       txh->txh_space_towrite += space;
+       if (txh)
+               txh->txh_space_towrite += space;
 }
 
 int
@@ -929,7 +924,7 @@ dmu_tx_try_assign(dmu_tx_t *tx, uint64_t txg_how)
        uint64_t memory, asize, fsize, usize;
        uint64_t towrite, tofree, tooverwrite, tounref, tohold, fudge;
 
-       ASSERT3U(tx->tx_txg, ==, 0);
+       ASSERT0(tx->tx_txg);
 
        if (tx->tx_err) {
                DMU_TX_STAT_BUMP(dmu_tx_error);
@@ -1095,12 +1090,15 @@ dmu_tx_unassign(dmu_tx_t *tx)
 int
 dmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how)
 {
+       hrtime_t before, after;
        int err;
 
        ASSERT(tx->tx_txg == 0);
        ASSERT(txg_how != 0);
        ASSERT(!dsl_pool_sync_context(tx->tx_pool));
 
+       before = gethrtime();
+
        while ((err = dmu_tx_try_assign(tx, txg_how)) != 0) {
                dmu_tx_unassign(tx);
 
@@ -1112,6 +1110,11 @@ dmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how)
 
        txg_rele_to_quiesce(&tx->tx_txgh);
 
+       after = gethrtime();
+
+       dsl_pool_tx_assign_add_usecs(tx->tx_pool,
+           (after - before) / NSEC_PER_USEC);
+
        return (0);
 }
 
@@ -1318,6 +1321,8 @@ dmu_tx_hold_spill(dmu_tx_t *tx, uint64_t object)
 
        txh = dmu_tx_hold_object_impl(tx, tx->tx_objset, object,
            THT_SPILL, 0, 0);
+       if (txh == NULL)
+               return;
 
        dn = txh->txh_dnode;