]> git.proxmox.com Git - mirror_zfs-debian.git/blobdiff - module/zfs/spa_misc.c
Imported Upstream version 0.6.5.3
[mirror_zfs-debian.git] / module / zfs / spa_misc.c
index 0ca9f3a7a622a89bf7fd49fc2ef876e806a089f3..409dce12121276ce97e08d0a3477112e4957c1a5 100644 (file)
@@ -20,8 +20,9 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
  */
 
 #include <sys/zfs_context.h>
@@ -34,6 +35,7 @@
 #include <sys/zap.h>
 #include <sys/zil.h>
 #include <sys/vdev_impl.h>
+#include <sys/vdev_file.h>
 #include <sys/metaslab.h>
 #include <sys/uberblock_impl.h>
 #include <sys/txg.h>
@@ -48,6 +50,7 @@
 #include <sys/metaslab_impl.h>
 #include <sys/arc.h>
 #include <sys/ddt.h>
+#include <sys/kstat.h>
 #include "zfs_prop.h"
 #include "zfeature_common.h"
 
 static avl_tree_t spa_namespace_avl;
 kmutex_t spa_namespace_lock;
 static kcondvar_t spa_namespace_cv;
-static int spa_active_count;
 int spa_max_replication_override = SPA_DVAS_PER_BP;
 
 static kmutex_t spa_spare_lock;
@@ -236,23 +238,104 @@ static avl_tree_t spa_l2cache_avl;
 kmem_cache_t *spa_buffer_pool;
 int spa_mode_global;
 
+#ifdef ZFS_DEBUG
+/* Everything except dprintf and spa is on by default in debug builds */
+int zfs_flags = ~(ZFS_DEBUG_DPRINTF | ZFS_DEBUG_SPA);
+#else
+int zfs_flags = 0;
+#endif
+
+/*
+ * zfs_recover can be set to nonzero to attempt to recover from
+ * otherwise-fatal errors, typically caused by on-disk corruption.  When
+ * set, calls to zfs_panic_recover() will turn into warning messages.
+ * This should only be used as a last resort, as it typically results
+ * in leaked space, or worse.
+ */
+int zfs_recover = B_FALSE;
+
+/*
+ * If destroy encounters an EIO while reading metadata (e.g. indirect
+ * blocks), space referenced by the missing metadata can not be freed.
+ * Normally this causes the background destroy to become "stalled", as
+ * it is unable to make forward progress.  While in this stalled state,
+ * all remaining space to free from the error-encountering filesystem is
+ * "temporarily leaked".  Set this flag to cause it to ignore the EIO,
+ * permanently leak the space from indirect blocks that can not be read,
+ * and continue to free everything else that it can.
+ *
+ * The default, "stalling" behavior is useful if the storage partially
+ * fails (i.e. some but not all i/os fail), and then later recovers.  In
+ * this case, we will be able to continue pool operations while it is
+ * partially failed, and when it recovers, we can continue to free the
+ * space, with no leaks.  However, note that this case is actually
+ * fairly rare.
+ *
+ * Typically pools either (a) fail completely (but perhaps temporarily,
+ * e.g. a top-level vdev going offline), or (b) have localized,
+ * permanent errors (e.g. disk returns the wrong data due to bit flip or
+ * firmware bug).  In case (a), this setting does not matter because the
+ * pool will be suspended and the sync thread will not be able to make
+ * forward progress regardless.  In case (b), because the error is
+ * permanent, the best we can do is leak the minimum amount of space,
+ * which is what setting this flag will do.  Therefore, it is reasonable
+ * for this flag to normally be set, but we chose the more conservative
+ * approach of not setting it, so that there is no possibility of
+ * leaking space in the "partial temporary" failure case.
+ */
+int zfs_free_leak_on_eio = B_FALSE;
+
 /*
- * Expiration time in units of zfs_txg_synctime_ms. This value has two
- * meanings. First it is used to determine when the spa_deadman logic
- * should fire. By default the spa_deadman will fire if spa_sync has
- * not completed in 1000 * zfs_txg_synctime_ms (i.e. 1000 seconds).
- * Secondly, the value determines if an I/O is considered "hung".
- * Any I/O that has not completed in zfs_deadman_synctime is considered
- * "hung" resulting in a zevent being posted.
- * 1000 zfs_txg_synctime_ms (i.e. 1000 seconds).
+ * Expiration time in milliseconds. This value has two meanings. First it is
+ * used to determine when the spa_deadman() logic should fire. By default the
+ * spa_deadman() will fire if spa_sync() has not completed in 1000 seconds.
+ * Secondly, the value determines if an I/O is considered "hung". Any I/O that
+ * has not completed in zfs_deadman_synctime_ms is considered "hung" resulting
+ * in a system panic.
  */
-unsigned long zfs_deadman_synctime = 1000ULL;
+unsigned long zfs_deadman_synctime_ms = 1000000ULL;
 
 /*
  * By default the deadman is enabled.
  */
 int zfs_deadman_enabled = 1;
 
+/*
+ * The worst case is single-sector max-parity RAID-Z blocks, in which
+ * case the space requirement is exactly (VDEV_RAIDZ_MAXPARITY + 1)
+ * times the size; so just assume that.  Add to this the fact that
+ * we can have up to 3 DVAs per bp, and one more factor of 2 because
+ * the block may be dittoed with up to 3 DVAs by ddt_sync().  All together,
+ * the worst case is:
+ *     (VDEV_RAIDZ_MAXPARITY + 1) * SPA_DVAS_PER_BP * 2 == 24
+ */
+int spa_asize_inflation = 24;
+
+/*
+ * Normally, we don't allow the last 3.2% (1/(2^spa_slop_shift)) of space in
+ * the pool to be consumed.  This ensures that we don't run the pool
+ * completely out of space, due to unaccounted changes (e.g. to the MOS).
+ * It also limits the worst-case time to allocate space.  If we have
+ * less than this amount of free space, most ZPL operations (e.g. write,
+ * create) will return ENOSPC.
+ *
+ * Certain operations (e.g. file removal, most administrative actions) can
+ * use half the slop space.  They will only return ENOSPC if less than half
+ * the slop space is free.  Typically, once the pool has less than the slop
+ * space free, the user will use these operations to free up space in the pool.
+ * These are the operations that call dsl_pool_adjustedsize() with the netfree
+ * argument set to TRUE.
+ *
+ * A very restricted set of operations are always permitted, regardless of
+ * the amount of free space.  These are the operations that call
+ * dsl_sync_task(ZFS_SPACE_CHECK_NONE), e.g. "zfs destroy".  If these
+ * operations result in a net increase in the amount of space used,
+ * it is possible to run the pool completely out of space, causing it to
+ * be permanently read-only.
+ *
+ * See also the comments in zfs_space_check_t.
+ */
+int spa_slop_shift = 5;
 
 /*
  * ==========================================================================
@@ -268,7 +351,7 @@ spa_config_lock_init(spa_t *spa)
                spa_config_lock_t *scl = &spa->spa_config_lock[i];
                mutex_init(&scl->scl_lock, NULL, MUTEX_DEFAULT, NULL);
                cv_init(&scl->scl_cv, NULL, CV_DEFAULT, NULL);
-               refcount_create(&scl->scl_count);
+               refcount_create_untracked(&scl->scl_count);
                scl->scl_writer = NULL;
                scl->scl_write_wanted = 0;
        }
@@ -326,6 +409,8 @@ spa_config_enter(spa_t *spa, int locks, void *tag, krw_t rw)
        int wlocks_held = 0;
        int i;
 
+       ASSERT3U(SCL_LOCKS, <, sizeof (wlocks_held) * NBBY);
+
        for (i = 0; i < SCL_LOCKS; i++) {
                spa_config_lock_t *scl = &spa->spa_config_lock[i];
                if (scl->scl_writer == curthread)
@@ -406,27 +491,22 @@ spa_lookup(const char *name)
        static spa_t search;    /* spa_t is large; don't allocate on stack */
        spa_t *spa;
        avl_index_t where;
-       char c = 0;
        char *cp;
 
        ASSERT(MUTEX_HELD(&spa_namespace_lock));
 
+       (void) strlcpy(search.spa_name, name, sizeof (search.spa_name));
+
        /*
         * If it's a full dataset name, figure out the pool name and
         * just use that.
         */
-       cp = strpbrk(name, "/@");
-       if (cp) {
-               c = *cp;
+       cp = strpbrk(search.spa_name, "/@#");
+       if (cp != NULL)
                *cp = '\0';
-       }
 
-       (void) strlcpy(search.spa_name, name, sizeof (search.spa_name));
        spa = avl_find(&spa_namespace_avl, &search, &where);
 
-       if (cp)
-               *cp = c;
-
        return (spa);
 }
 
@@ -447,7 +527,7 @@ spa_deadman(void *arg)
                vdev_deadman(spa->spa_root_vdev);
 
        spa->spa_deadman_tqid = taskq_dispatch_delay(system_taskq,
-           spa_deadman, spa, TQ_SLEEP, ddi_get_lbolt() +
+           spa_deadman, spa, KM_SLEEP, ddi_get_lbolt() +
            NSEC_TO_TICK(spa->spa_deadman_synctime));
 }
 
@@ -462,22 +542,26 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
        spa_t *spa;
        spa_config_dirent_t *dp;
        int t;
+       int i;
 
        ASSERT(MUTEX_HELD(&spa_namespace_lock));
 
-       spa = kmem_zalloc(sizeof (spa_t), KM_PUSHPAGE | KM_NODEBUG);
+       spa = kmem_zalloc(sizeof (spa_t), KM_SLEEP);
 
        mutex_init(&spa->spa_async_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_errlist_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_errlog_lock, NULL, MUTEX_DEFAULT, NULL);
+       mutex_init(&spa->spa_evicting_os_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_history_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_proc_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_props_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_scrub_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_suspend_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_vdev_top_lock, NULL, MUTEX_DEFAULT, NULL);
+       mutex_init(&spa->spa_feat_stats_lock, NULL, MUTEX_DEFAULT, NULL);
 
        cv_init(&spa->spa_async_cv, NULL, CV_DEFAULT, NULL);
+       cv_init(&spa->spa_evicting_os_cv, NULL, CV_DEFAULT, NULL);
        cv_init(&spa->spa_proc_cv, NULL, CV_DEFAULT, NULL);
        cv_init(&spa->spa_scrub_io_cv, NULL, CV_DEFAULT, NULL);
        cv_init(&spa->spa_suspend_cv, NULL, CV_DEFAULT, NULL);
@@ -493,21 +577,19 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
        spa->spa_proc = &p0;
        spa->spa_proc_state = SPA_PROC_NONE;
 
-       spa->spa_deadman_synctime = zfs_deadman_synctime *
-           zfs_txg_synctime_ms * MICROSEC;
+       spa->spa_deadman_synctime = MSEC2NSEC(zfs_deadman_synctime_ms);
 
        refcount_create(&spa->spa_refcount);
        spa_config_lock_init(spa);
+       spa_stats_init(spa);
 
        avl_add(&spa_namespace_avl, spa);
 
        /*
         * Set the alternate root, if there is one.
         */
-       if (altroot) {
+       if (altroot)
                spa->spa_root = spa_strdup(altroot);
-               spa_active_count++;
-       }
 
        /*
         * Every pool starts with the default cachefile
@@ -515,12 +597,12 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
        list_create(&spa->spa_config_list, sizeof (spa_config_dirent_t),
            offsetof(spa_config_dirent_t, scd_link));
 
-       dp = kmem_zalloc(sizeof (spa_config_dirent_t), KM_PUSHPAGE);
+       dp = kmem_zalloc(sizeof (spa_config_dirent_t), KM_SLEEP);
        dp->scd_path = altroot ? NULL : spa_strdup(spa_config_path);
        list_insert_head(&spa->spa_config_list, dp);
 
        VERIFY(nvlist_alloc(&spa->spa_load_info, NV_UNIQUE_NAME,
-           KM_PUSHPAGE) == 0);
+           KM_SLEEP) == 0);
 
        if (config != NULL) {
                nvlist_t *features;
@@ -539,6 +621,20 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
                    KM_SLEEP) == 0);
        }
 
+       spa->spa_debug = ((zfs_flags & ZFS_DEBUG_SPA) != 0);
+
+       spa->spa_min_ashift = INT_MAX;
+       spa->spa_max_ashift = 0;
+
+       /*
+        * As a pool is being created, treat all features as disabled by
+        * setting SPA_FEATURE_DISABLED for all entries in the feature
+        * refcount cache.
+        */
+       for (i = 0; i < SPA_FEATURES; i++) {
+               spa->spa_feat_refcount_cache[i] = SPA_FEATURE_DISABLED;
+       }
+
        return (spa);
 }
 
@@ -555,16 +651,15 @@ spa_remove(spa_t *spa)
 
        ASSERT(MUTEX_HELD(&spa_namespace_lock));
        ASSERT(spa->spa_state == POOL_STATE_UNINITIALIZED);
+       ASSERT3U(refcount_count(&spa->spa_refcount), ==, 0);
 
        nvlist_free(spa->spa_config_splitting);
 
        avl_remove(&spa_namespace_avl, spa);
        cv_broadcast(&spa_namespace_cv);
 
-       if (spa->spa_root) {
+       if (spa->spa_root)
                spa_strfree(spa->spa_root);
-               spa_active_count--;
-       }
 
        while ((dp = list_head(&spa->spa_config_list)) != NULL) {
                list_remove(&spa->spa_config_list, dp);
@@ -577,16 +672,19 @@ spa_remove(spa_t *spa)
 
        nvlist_free(spa->spa_label_features);
        nvlist_free(spa->spa_load_info);
+       nvlist_free(spa->spa_feat_stats);
        spa_config_set(spa, NULL);
 
        refcount_destroy(&spa->spa_refcount);
 
+       spa_stats_destroy(spa);
        spa_config_lock_destroy(spa);
 
        for (t = 0; t < TXG_SIZE; t++)
                bplist_destroy(&spa->spa_free_bplist[t]);
 
        cv_destroy(&spa->spa_async_cv);
+       cv_destroy(&spa->spa_evicting_os_cv);
        cv_destroy(&spa->spa_proc_cv);
        cv_destroy(&spa->spa_scrub_io_cv);
        cv_destroy(&spa->spa_suspend_cv);
@@ -594,12 +692,14 @@ spa_remove(spa_t *spa)
        mutex_destroy(&spa->spa_async_lock);
        mutex_destroy(&spa->spa_errlist_lock);
        mutex_destroy(&spa->spa_errlog_lock);
+       mutex_destroy(&spa->spa_evicting_os_lock);
        mutex_destroy(&spa->spa_history_lock);
        mutex_destroy(&spa->spa_proc_lock);
        mutex_destroy(&spa->spa_props_lock);
        mutex_destroy(&spa->spa_scrub_lock);
        mutex_destroy(&spa->spa_suspend_lock);
        mutex_destroy(&spa->spa_vdev_top_lock);
+       mutex_destroy(&spa->spa_feat_stats_lock);
 
        kmem_free(spa, sizeof (spa_t));
 }
@@ -649,6 +749,20 @@ spa_close(spa_t *spa, void *tag)
        (void) refcount_remove(&spa->spa_refcount, tag);
 }
 
+/*
+ * Remove a reference to the given spa_t held by a dsl dir that is
+ * being asynchronously released.  Async releases occur from a taskq
+ * performing eviction of dsl datasets and dirs.  The namespace lock
+ * isn't held and the hold by the object being evicted may contribute to
+ * spa_minref (e.g. dataset or directory released during pool export),
+ * so the asserts in spa_close() do not apply.
+ */
+void
+spa_async_close(spa_t *spa, void *tag)
+{
+       (void) refcount_remove(&spa->spa_refcount, tag);
+}
+
 /*
  * Check to see if the spa refcount is zero.  Must be called with
  * spa_namespace_lock held.  We really compare against spa_minref, which is the
@@ -705,7 +819,7 @@ spa_aux_add(vdev_t *vd, avl_tree_t *avl)
        if ((aux = avl_find(avl, &search, &where)) != NULL) {
                aux->aux_count++;
        } else {
-               aux = kmem_zalloc(sizeof (spa_aux_t), KM_PUSHPAGE);
+               aux = kmem_zalloc(sizeof (spa_aux_t), KM_SLEEP);
                aux->aux_guid = vd->vdev_guid;
                aux->aux_count = 1;
                avl_insert(avl, aux, where);
@@ -976,7 +1090,7 @@ spa_vdev_config_exit(spa_t *spa, vdev_t *vd, uint64_t txg, int error, char *tag)
                txg_wait_synced(spa->spa_dsl_pool, txg);
 
        if (vd != NULL) {
-               ASSERT(!vd->vdev_detached || vd->vdev_dtl_smo.smo_object == 0);
+               ASSERT(!vd->vdev_detached || vd->vdev_dtl_sm == NULL);
                spa_config_enter(spa, SCL_ALL, spa, RW_WRITER);
                vdev_free(vd);
                spa_config_exit(spa, SCL_ALL, spa);
@@ -1084,17 +1198,27 @@ spa_vdev_state_exit(spa_t *spa, vdev_t *vd, int error)
  */
 
 void
-spa_activate_mos_feature(spa_t *spa, const char *feature)
-{
-       (void) nvlist_add_boolean(spa->spa_label_features, feature);
-       vdev_config_dirty(spa->spa_root_vdev);
+spa_activate_mos_feature(spa_t *spa, const char *feature, dmu_tx_t *tx)
+{
+       if (!nvlist_exists(spa->spa_label_features, feature)) {
+               fnvlist_add_boolean(spa->spa_label_features, feature);
+               /*
+                * When we are creating the pool (tx_txg==TXG_INITIAL), we can't
+                * dirty the vdev config because lock SCL_CONFIG is not held.
+                * Thankfully, in this case we don't need to dirty the config
+                * because it will be written out anyway when we finish
+                * creating the pool.
+                */
+               if (tx->tx_txg != TXG_INITIAL)
+                       vdev_config_dirty(spa->spa_root_vdev);
+       }
 }
 
 void
 spa_deactivate_mos_feature(spa_t *spa, const char *feature)
 {
-       (void) nvlist_remove_all(spa->spa_label_features, feature);
-       vdev_config_dirty(spa->spa_root_vdev);
+       if (nvlist_remove_all(spa->spa_label_features, feature) == 0)
+               vdev_config_dirty(spa->spa_root_vdev);
 }
 
 /*
@@ -1203,7 +1327,7 @@ spa_strdup(const char *s)
        char *new;
 
        len = strlen(s);
-       new = kmem_alloc(len + 1, KM_PUSHPAGE);
+       new = kmem_alloc(len + 1, KM_SLEEP);
        bcopy(s, new, len);
        new[len] = '\0';
 
@@ -1245,7 +1369,7 @@ spa_generate_guid(spa_t *spa)
 }
 
 void
-sprintf_blkptr(char *buf, const blkptr_t *bp)
+snprintf_blkptr(char *buf, size_t buflen, const blkptr_t *bp)
 {
        char type[256];
        char *checksum = NULL;
@@ -1263,11 +1387,15 @@ sprintf_blkptr(char *buf, const blkptr_t *bp)
                        (void) strlcpy(type, dmu_ot[BP_GET_TYPE(bp)].ot_name,
                            sizeof (type));
                }
-               checksum = zio_checksum_table[BP_GET_CHECKSUM(bp)].ci_name;
+               if (!BP_IS_EMBEDDED(bp)) {
+                       checksum =
+                           zio_checksum_table[BP_GET_CHECKSUM(bp)].ci_name;
+               }
                compress = zio_compress_table[BP_GET_COMPRESS(bp)].ci_name;
        }
 
-       SPRINTF_BLKPTR(snprintf, ' ', buf, bp, type, checksum, compress);
+       SNPRINTF_BLKPTR(snprintf, ' ', buf, buflen, bp, type, checksum,
+           compress);
 }
 
 void
@@ -1285,9 +1413,19 @@ spa_freeze(spa_t *spa)
                txg_wait_synced(spa_get_dsl(spa), freeze_txg);
 }
 
+void
+zfs_panic_recover(const char *fmt, ...)
+{
+       va_list adx;
+
+       va_start(adx, fmt);
+       vcmn_err(zfs_recover ? CE_WARN : CE_PANIC, fmt, adx);
+       va_end(adx);
+}
+
 /*
  * This is a stripped-down version of strtoull, suitable only for converting
- * lowercase hexidecimal numbers that don't overflow.
+ * lowercase hexadecimal numbers that don't overflow.
  */
 uint64_t
 strtonum(const char *str, char **nptr)
@@ -1452,14 +1590,19 @@ spa_freeze_txg(spa_t *spa)
 uint64_t
 spa_get_asize(spa_t *spa, uint64_t lsize)
 {
-       /*
-        * The worst case is single-sector max-parity RAID-Z blocks, in which
-        * case the space requirement is exactly (VDEV_RAIDZ_MAXPARITY + 1)
-        * times the size; so just assume that.  Add to this the fact that
-        * we can have up to 3 DVAs per bp, and one more factor of 2 because
-        * the block may be dittoed with up to 3 DVAs by ddt_sync().
-        */
-       return (lsize * (VDEV_RAIDZ_MAXPARITY + 1) * SPA_DVAS_PER_BP * 2);
+       return (lsize * spa_asize_inflation);
+}
+
+/*
+ * Return the amount of slop space in bytes.  It is 1/32 of the pool (3.2%),
+ * or at least 32MB.
+ *
+ * See the comment above spa_slop_shift for details.
+ */
+uint64_t
+spa_get_slop_space(spa_t *spa) {
+       uint64_t space = spa_get_dspace(spa);
+       return (MAX(space >> spa_slop_shift, SPA_MINDEVSIZE >> 1));
 }
 
 uint64_t
@@ -1515,6 +1658,34 @@ spa_log_class(spa_t *spa)
        return (spa->spa_log_class);
 }
 
+void
+spa_evicting_os_register(spa_t *spa, objset_t *os)
+{
+       mutex_enter(&spa->spa_evicting_os_lock);
+       list_insert_head(&spa->spa_evicting_os_list, os);
+       mutex_exit(&spa->spa_evicting_os_lock);
+}
+
+void
+spa_evicting_os_deregister(spa_t *spa, objset_t *os)
+{
+       mutex_enter(&spa->spa_evicting_os_lock);
+       list_remove(&spa->spa_evicting_os_list, os);
+       cv_broadcast(&spa->spa_evicting_os_cv);
+       mutex_exit(&spa->spa_evicting_os_lock);
+}
+
+void
+spa_evicting_os_wait(spa_t *spa)
+{
+       mutex_enter(&spa->spa_evicting_os_lock);
+       while (!list_is_empty(&spa->spa_evicting_os_list))
+               cv_wait(&spa->spa_evicting_os_cv, &spa->spa_evicting_os_lock);
+       mutex_exit(&spa->spa_evicting_os_lock);
+
+       dmu_buf_user_evict_wait();
+}
+
 int
 spa_max_replication(spa_t *spa)
 {
@@ -1550,7 +1721,9 @@ dva_get_dsize_sync(spa_t *spa, const dva_t *dva)
 
        if (asize != 0 && spa->spa_deflate) {
                vdev_t *vd = vdev_lookup_top(spa, DVA_GET_VDEV(dva));
-               dsize = (asize >> SPA_MINBLOCKSHIFT) * vd->vdev_deflate_ratio;
+               if (vd != NULL)
+                       dsize = (asize >> SPA_MINBLOCKSHIFT) *
+                           vd->vdev_deflate_ratio;
        }
 
        return (dsize);
@@ -1562,7 +1735,7 @@ bp_get_dsize_sync(spa_t *spa, const blkptr_t *bp)
        uint64_t dsize = 0;
        int d;
 
-       for (d = 0; d < SPA_DVAS_PER_BP; d++)
+       for (d = 0; d < BP_GET_NDVAS(bp); d++)
                dsize += dva_get_dsize_sync(spa, &bp->blk_dva[d]);
 
        return (dsize);
@@ -1576,7 +1749,7 @@ bp_get_dsize(spa_t *spa, const blkptr_t *bp)
 
        spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
 
-       for (d = 0; d < SPA_DVAS_PER_BP; d++)
+       for (d = 0; d < BP_GET_NDVAS(bp); d++)
                dsize += dva_get_dsize_sync(spa, &bp->blk_dva[d]);
 
        spa_config_exit(spa, SCL_VDEV, FTAG);
@@ -1630,10 +1803,28 @@ spa_init(int mode)
 
        spa_mode_global = mode;
 
+#ifndef _KERNEL
+       if (spa_mode_global != FREAD && dprintf_find_string("watch")) {
+               struct sigaction sa;
+
+               sa.sa_flags = SA_SIGINFO;
+               sigemptyset(&sa.sa_mask);
+               sa.sa_sigaction = arc_buf_sigsegv;
+
+               if (sigaction(SIGSEGV, &sa, NULL) == -1) {
+                       perror("could not enable watchpoints: "
+                           "sigaction(SIGSEGV, ...) = ");
+               } else {
+                       arc_watch = B_TRUE;
+               }
+       }
+#endif
+
        fm_init();
        refcount_init();
        unique_init();
-       space_map_init();
+       range_tree_init();
+       ddt_init();
        zio_init();
        dmu_init();
        zil_init();
@@ -1656,7 +1847,8 @@ spa_fini(void)
        zil_fini();
        dmu_fini();
        zio_fini();
-       space_map_fini();
+       ddt_fini();
+       range_tree_fini();
        unique_fini();
        refcount_fini();
        fm_fini();
@@ -1706,6 +1898,16 @@ spa_writeable(spa_t *spa)
        return (!!(spa->spa_mode & FWRITE));
 }
 
+/*
+ * Returns true if there is a pending sync task in any of the current
+ * syncing txg, the current quiescing txg, or the current open txg.
+ */
+boolean_t
+spa_has_pending_synctask(spa_t *spa)
+{
+       return (!txg_all_lists_empty(&spa->spa_dsl_pool->dp_sync_tasks));
+}
+
 int
 spa_mode(spa_t *spa)
 {
@@ -1757,7 +1959,7 @@ spa_scan_get_stats(spa_t *spa, pool_scan_stat_t *ps)
        dsl_scan_t *scn = spa->spa_dsl_pool ? spa->spa_dsl_pool->dp_scan : NULL;
 
        if (scn == NULL || scn->scn_phys.scn_func == POOL_SCAN_NONE)
-               return (ENOENT);
+               return (SET_ERROR(ENOENT));
        bzero(ps, sizeof (pool_scan_stat_t));
 
        /* data stored on disk */
@@ -1784,6 +1986,15 @@ spa_debug_enabled(spa_t *spa)
        return (spa->spa_debug);
 }
 
+int
+spa_maxblocksize(spa_t *spa)
+{
+       if (spa_feature_is_enabled(spa, SPA_FEATURE_LARGE_BLOCKS))
+               return (SPA_MAXBLOCKSIZE);
+       else
+               return (SPA_OLD_MAXBLOCKSIZE);
+}
+
 #if defined(_KERNEL) && defined(HAVE_SPL)
 /* Namespace manipulation */
 EXPORT_SYMBOL(spa_lookup);
@@ -1839,6 +2050,7 @@ EXPORT_SYMBOL(spa_suspended);
 EXPORT_SYMBOL(spa_bootfs);
 EXPORT_SYMBOL(spa_delegation);
 EXPORT_SYMBOL(spa_meta_objset);
+EXPORT_SYMBOL(spa_maxblocksize);
 
 /* Miscellaneous support routines */
 EXPORT_SYMBOL(spa_rename);
@@ -1847,7 +2059,7 @@ EXPORT_SYMBOL(spa_strdup);
 EXPORT_SYMBOL(spa_strfree);
 EXPORT_SYMBOL(spa_get_random);
 EXPORT_SYMBOL(spa_generate_guid);
-EXPORT_SYMBOL(sprintf_blkptr);
+EXPORT_SYMBOL(snprintf_blkptr);
 EXPORT_SYMBOL(spa_freeze);
 EXPORT_SYMBOL(spa_upgrade);
 EXPORT_SYMBOL(spa_evict_all);
@@ -1863,9 +2075,26 @@ EXPORT_SYMBOL(spa_mode);
 
 EXPORT_SYMBOL(spa_namespace_lock);
 
-module_param(zfs_deadman_synctime, ulong, 0644);
-MODULE_PARM_DESC(zfs_deadman_synctime,"Expire in units of zfs_txg_synctime_ms");
+module_param(zfs_flags, uint, 0644);
+MODULE_PARM_DESC(zfs_flags, "Set additional debugging flags");
+
+module_param(zfs_recover, int, 0644);
+MODULE_PARM_DESC(zfs_recover, "Set to attempt to recover from fatal errors");
+
+module_param(zfs_free_leak_on_eio, int, 0644);
+MODULE_PARM_DESC(zfs_free_leak_on_eio,
+       "Set to ignore IO errors during free and permanently leak the space");
+
+module_param(zfs_deadman_synctime_ms, ulong, 0644);
+MODULE_PARM_DESC(zfs_deadman_synctime_ms, "Expiration time in milliseconds");
 
 module_param(zfs_deadman_enabled, int, 0644);
 MODULE_PARM_DESC(zfs_deadman_enabled, "Enable deadman timer");
+
+module_param(spa_asize_inflation, int, 0644);
+MODULE_PARM_DESC(spa_asize_inflation,
+       "SPA size estimate multiplication factor");
+
+module_param(spa_slop_shift, int, 0644);
+MODULE_PARM_DESC(spa_slop_shift, "Reserved free space in pool");
 #endif