Illumos #1644, #1645, #1646, #1647, #1708
[zfs.git] / module / zfs / dsl_pool.c
index a3c1457..3b285df 100644 (file)
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
  */
 
 #include <sys/dsl_pool.h>
@@ -44,10 +45,10 @@ int zfs_no_write_throttle = 0;
 int zfs_write_limit_shift = 3;                 /* 1/8th of physical memory */
 int zfs_txg_synctime_ms = 1000;                /* target millisecs to sync a txg */
 
-uint64_t zfs_write_limit_min = 32 << 20;       /* min write limit is 32MB */
-uint64_t zfs_write_limit_max = 0;              /* max data payload per txg */
-uint64_t zfs_write_limit_inflated = 0;
-uint64_t zfs_write_limit_override = 0;
+unsigned long zfs_write_limit_min = 32 << 20;  /* min write limit is 32MB */
+unsigned long zfs_write_limit_max = 0;         /* max data payload per txg */
+unsigned long zfs_write_limit_inflated = 0;
+unsigned long zfs_write_limit_override = 0;
 
 kmutex_t zfs_write_limit_lock;
 
@@ -92,7 +93,7 @@ dsl_pool_open_impl(spa_t *spa, uint64_t txg)
 
        mutex_init(&dp->dp_lock, NULL, MUTEX_DEFAULT, NULL);
 
-       dp->dp_vnrele_taskq = taskq_create("zfs_vn_rele_taskq", 1, minclsyspri,
+       dp->dp_iput_taskq = taskq_create("zfs_iput_taskq", 1, minclsyspri,
            1, 4, 0);
 
        return (dp);
@@ -214,7 +215,7 @@ dsl_pool_close(dsl_pool_t *dp)
        dsl_scan_fini(dp);
        rw_destroy(&dp->dp_config_rwlock);
        mutex_destroy(&dp->dp_lock);
-       taskq_destroy(dp->dp_vnrele_taskq);
+       taskq_destroy(dp->dp_iput_taskq);
        if (dp->dp_blkstats)
                kmem_free(dp->dp_blkstats, sizeof (zfs_all_blkstats_t));
        kmem_free(dp, sizeof (dsl_pool_t));
@@ -275,8 +276,8 @@ dsl_pool_create(spa_t *spa, nvlist_t *zplprops, uint64_t txg)
 
        /* create the root objset */
        VERIFY(0 == dsl_dataset_hold_obj(dp, obj, FTAG, &ds));
-       os = dmu_objset_create_impl(dp->dp_spa, ds,
-           dsl_dataset_get_blkptr(ds), DMU_OST_ZFS, tx);
+       VERIFY(NULL != (os = dmu_objset_create_impl(dp->dp_spa, ds,
+           dsl_dataset_get_blkptr(ds), DMU_OST_ZFS, tx)));
 #ifdef _KERNEL
        zfs_create_fs(os, kcred, zplprops, tx);
 #endif
@@ -291,7 +292,10 @@ static int
 deadlist_enqueue_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
 {
        dsl_deadlist_t *dl = arg;
+       dsl_pool_t *dp = dmu_objset_pool(dl->dl_os);
+       rw_enter(&dp->dp_config_rwlock, RW_READER);
        dsl_deadlist_insert(dl, bp, tx);
+       rw_exit(&dp->dp_config_rwlock);
        return (0);
 }
 
@@ -322,7 +326,7 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
        start = gethrtime();
 
        zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
-       while (ds = txg_list_remove(&dp->dp_dirty_datasets, txg)) {
+       while ((ds = txg_list_remove(&dp->dp_dirty_datasets, txg))) {
                /*
                 * We must not sync any non-MOS datasets twice, because
                 * we may have taken a snapshot of them.  However, we
@@ -350,7 +354,7 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
         * whose ds_bp will be rewritten when we do this 2nd sync.
         */
        zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
-       while (ds = txg_list_remove(&dp->dp_dirty_datasets, txg)) {
+       while ((ds = txg_list_remove(&dp->dp_dirty_datasets, txg))) {
                ASSERT(list_link_active(&ds->ds_synced_link));
                dmu_buf_rele(ds->ds_dbuf, ds);
                dsl_dataset_sync(ds, zio, tx);
@@ -367,7 +371,7 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
                    deadlist_enqueue_cb, &ds->ds_deadlist, tx);
        }
 
-       while (dstg = txg_list_remove(&dp->dp_sync_tasks, txg)) {
+       while ((dstg = txg_list_remove(&dp->dp_sync_tasks, txg))) {
                /*
                 * No more sync tasks should have been added while we
                 * were syncing.
@@ -378,7 +382,7 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
        DTRACE_PROBE(pool_sync__3task);
 
        start = gethrtime();
-       while (dd = txg_list_remove(&dp->dp_dirty_dirs, txg))
+       while ((dd = txg_list_remove(&dp->dp_dirty_dirs, txg)))
                dsl_dir_sync(dd, tx);
        write_time += gethrtime() - start;
 
@@ -448,7 +452,7 @@ dsl_pool_sync_done(dsl_pool_t *dp, uint64_t txg)
        dsl_dataset_t *ds;
        objset_t *os;
 
-       while (ds = list_head(&dp->dp_synced_datasets)) {
+       while ((ds = list_head(&dp->dp_synced_datasets))) {
                list_remove(&dp->dp_synced_datasets, ds);
                os = ds->ds_objset;
                zil_clean(os->os_zil, txg);
@@ -517,8 +521,10 @@ dsl_pool_tempreserve_space(dsl_pool_t *dp, uint64_t space, dmu_tx_t *tx)
                reserved = dp->dp_space_towrite[tx->tx_txg & TXG_MASK]
                    + dp->dp_tempreserved[tx->tx_txg & TXG_MASK] / 2;
 
-               if (reserved && reserved > write_limit)
+               if (reserved && reserved > write_limit) {
+                       DMU_TX_STAT_BUMP(dmu_tx_write_limit);
                        return (ERESTART);
+               }
        }
 
        atomic_add_64(&dp->dp_tempreserved[tx->tx_txg & TXG_MASK], space);
@@ -738,9 +744,9 @@ dsl_pool_create_origin(dsl_pool_t *dp, dmu_tx_t *tx)
 }
 
 taskq_t *
-dsl_pool_vnrele_taskq(dsl_pool_t *dp)
+dsl_pool_iput_taskq(dsl_pool_t *dp)
 {
-       return (dp->dp_vnrele_taskq);
+       return (dp->dp_iput_taskq);
 }
 
 /*
@@ -847,3 +853,26 @@ dsl_pool_user_release(dsl_pool_t *dp, uint64_t dsobj, const char *tag,
        return (dsl_pool_user_hold_rele_impl(dp, dsobj, tag, NULL,
            tx, B_FALSE));
 }
+
+#if defined(_KERNEL) && defined(HAVE_SPL)
+module_param(zfs_no_write_throttle, int, 0644);
+MODULE_PARM_DESC(zfs_no_write_throttle, "Disable write throttling");
+
+module_param(zfs_write_limit_shift, int, 0444);
+MODULE_PARM_DESC(zfs_write_limit_shift, "log2(fraction of memory) per txg");
+
+module_param(zfs_txg_synctime_ms, int, 0644);
+MODULE_PARM_DESC(zfs_txg_synctime_ms, "Target milliseconds between tgx sync");
+
+module_param(zfs_write_limit_min, ulong, 0444);
+MODULE_PARM_DESC(zfs_write_limit_min, "Min tgx write limit");
+
+module_param(zfs_write_limit_max, ulong, 0444);
+MODULE_PARM_DESC(zfs_write_limit_max, "Max tgx write limit");
+
+module_param(zfs_write_limit_inflated, ulong, 0444);
+MODULE_PARM_DESC(zfs_write_limit_inflated, "Inflated tgx write limit");
+
+module_param(zfs_write_limit_override, ulong, 0444);
+MODULE_PARM_DESC(zfs_write_limit_override, "Override tgx write limit");
+#endif