]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/spa.c
Fix hung z_zvol tasks during 'zfs receive'
[mirror_zfs.git] / module / zfs / spa.c
index 0604742ab17acd2b1a23d615be90f777af07e652..4b6196cc3610105e80d4671a730cbdbb6853934a 100644 (file)
@@ -353,7 +353,7 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp)
                zprop_source_t src = ZPROP_SRC_DEFAULT;
                zpool_prop_t prop;
 
-               if ((prop = zpool_name_to_prop(za.za_name)) == ZPROP_INVAL)
+               if ((prop = zpool_name_to_prop(za.za_name)) == ZPOOL_PROP_INVAL)
                        continue;
 
                switch (za.za_integer_length) {
@@ -440,8 +440,8 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
                const char *propname = nvpair_name(elem);
                zpool_prop_t prop = zpool_name_to_prop(propname);
 
-               switch ((int)prop) {
-               case ZPROP_INVAL:
+               switch (prop) {
+               case ZPOOL_PROP_INVAL:
                        if (!zpool_prop_feature(propname)) {
                                error = SET_ERROR(EINVAL);
                                break;
@@ -698,7 +698,7 @@ spa_prop_set(spa_t *spa, nvlist_t *nvp)
                    prop == ZPOOL_PROP_READONLY)
                        continue;
 
-               if (prop == ZPOOL_PROP_VERSION || prop == ZPROP_INVAL) {
+               if (prop == ZPOOL_PROP_VERSION || prop == ZPOOL_PROP_INVAL) {
                        uint64_t ver;
 
                        if (prop == ZPOOL_PROP_VERSION) {
@@ -1186,9 +1186,17 @@ spa_activate(spa_t *spa, int mode)
        spa->spa_zvol_taskq = taskq_create("z_zvol", 1, defclsyspri,
            1, INT_MAX, 0);
 
+       /*
+        * Taskq dedicated to prefetcher threads: this is used to prevent the
+        * pool traverse code from monopolizing the global (and limited)
+        * system_taskq by inappropriately scheduling long running tasks on it.
+        */
+       spa->spa_prefetch_taskq = taskq_create("z_prefetch", boot_ncpus,
+           defclsyspri, 1, INT_MAX, TASKQ_DYNAMIC);
+
        /*
         * The taskq to upgrade datasets in this pool. Currently used by
-        * feature SPA_FEATURE_USEROBJ_ACCOUNTING.
+        * feature SPA_FEATURE_USEROBJ_ACCOUNTING/SPA_FEATURE_PROJECT_QUOTA.
         */
        spa->spa_upgrade_taskq = taskq_create("z_upgrade", boot_ncpus,
            defclsyspri, 1, INT_MAX, TASKQ_DYNAMIC);
@@ -1213,6 +1221,11 @@ spa_deactivate(spa_t *spa)
                spa->spa_zvol_taskq = NULL;
        }
 
+       if (spa->spa_prefetch_taskq) {
+               taskq_destroy(spa->spa_prefetch_taskq);
+               spa->spa_prefetch_taskq = NULL;
+       }
+
        if (spa->spa_upgrade_taskq) {
                taskq_destroy(spa->spa_upgrade_taskq);
                spa->spa_upgrade_taskq = NULL;
@@ -1563,7 +1576,7 @@ spa_load_spares(spa_t *spa)
 static void
 spa_load_l2cache(spa_t *spa)
 {
-       nvlist_t **l2cache;
+       nvlist_t **l2cache = NULL;
        uint_t nl2cache;
        int i, j, oldnvdevs;
        uint64_t guid;
@@ -1647,7 +1660,9 @@ spa_load_l2cache(spa_t *spa)
        VERIFY(nvlist_remove(sav->sav_config, ZPOOL_CONFIG_L2CACHE,
            DATA_TYPE_NVLIST_ARRAY) == 0);
 
-       l2cache = kmem_alloc(sav->sav_count * sizeof (void *), KM_SLEEP);
+       if (sav->sav_count > 0)
+               l2cache = kmem_alloc(sav->sav_count * sizeof (void *),
+                   KM_SLEEP);
        for (i = 0; i < sav->sav_count; i++)
                l2cache[i] = vdev_config_generate(spa,
                    sav->sav_vdevs[i], B_TRUE, VDEV_CONFIG_L2CACHE);
@@ -1996,7 +2011,7 @@ spa_load_verify_done(zio_t *zio)
        }
 
        mutex_enter(&spa->spa_scrub_lock);
-       spa->spa_scrub_inflight--;
+       spa->spa_load_verify_ios--;
        cv_broadcast(&spa->spa_scrub_io_cv);
        mutex_exit(&spa->spa_scrub_lock);
 }
@@ -2030,9 +2045,9 @@ spa_load_verify_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
        size_t size = BP_GET_PSIZE(bp);
 
        mutex_enter(&spa->spa_scrub_lock);
-       while (spa->spa_scrub_inflight >= spa_load_verify_maxinflight)
+       while (spa->spa_load_verify_ios >= spa_load_verify_maxinflight)
                cv_wait(&spa->spa_scrub_io_cv, &spa->spa_scrub_lock);
-       spa->spa_scrub_inflight++;
+       spa->spa_load_verify_ios++;
        mutex_exit(&spa->spa_scrub_lock);
 
        zio_nowait(zio_read(rio, spa, bp, abd_alloc_for_io(size, B_FALSE), size,
@@ -2330,7 +2345,8 @@ vdev_count_verify_zaps(vdev_t *vd)
  * Determine whether the activity check is required.
  */
 static boolean_t
-spa_activity_check_required(spa_t *spa, uberblock_t *ub, nvlist_t *config)
+spa_activity_check_required(spa_t *spa, uberblock_t *ub, nvlist_t *label,
+    nvlist_t *config)
 {
        uint64_t state = 0;
        uint64_t hostid = 0;
@@ -2347,7 +2363,6 @@ spa_activity_check_required(spa_t *spa, uberblock_t *ub, nvlist_t *config)
        }
 
        (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, &state);
-       (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
 
        /*
         * Disable the MMP activity check - This is used by zdb which
@@ -2373,8 +2388,12 @@ spa_activity_check_required(spa_t *spa, uberblock_t *ub, nvlist_t *config)
 
        /*
         * Allow the activity check to be skipped when importing the pool
-        * on the same host which last imported it.
+        * on the same host which last imported it.  Since the hostid from
+        * configuration may be stale use the one read from the label.
         */
+       if (nvlist_exists(label, ZPOOL_CONFIG_HOSTID))
+               hostid = fnvlist_lookup_uint64(label, ZPOOL_CONFIG_HOSTID);
+
        if (hostid == spa_get_hostid())
                return (B_FALSE);
 
@@ -2639,7 +2658,7 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
         * pool is truly inactive and can be safely imported.  Prevent
         * hosts which don't have a hostid set from importing the pool.
         */
-       activity_check = spa_activity_check_required(spa, ub, config);
+       activity_check = spa_activity_check_required(spa, ub, label, config);
        if (activity_check) {
                if (ub->ub_mmp_magic == MMP_MAGIC && ub->ub_mmp_delay &&
                    spa_get_hostid() == 0) {
@@ -3760,10 +3779,14 @@ spa_get_stats(const char *name, nvlist_t **config,
                            ZPOOL_CONFIG_ERRCOUNT,
                            spa_get_errlog_size(spa)) == 0);
 
-                       if (spa_suspended(spa))
+                       if (spa_suspended(spa)) {
                                VERIFY(nvlist_add_uint64(*config,
                                    ZPOOL_CONFIG_SUSPENDED,
                                    spa->spa_failmode) == 0);
+                               VERIFY(nvlist_add_uint64(*config,
+                                   ZPOOL_CONFIG_SUSPENDED_REASON,
+                                   spa->spa_suspended) == 0);
+                       }
 
                        spa_add_spares(spa, *config);
                        spa_add_l2cache(spa, *config);
@@ -6535,9 +6558,8 @@ spa_sync_props(void *arg, dmu_tx_t *tx)
                zprop_type_t proptype;
                spa_feature_t fid;
 
-               prop = zpool_name_to_prop(nvpair_name(elem));
-               switch ((int)prop) {
-               case ZPROP_INVAL:
+               switch (prop = zpool_name_to_prop(nvpair_name(elem))) {
+               case ZPOOL_PROP_INVAL:
                        /*
                         * We checked this earlier in spa_prop_validate().
                         */
@@ -6979,7 +7001,7 @@ spa_sync(spa_t *spa, uint64_t txg)
 
                if (error == 0)
                        break;
-               zio_suspend(spa, NULL);
+               zio_suspend(spa, NULL, ZIO_SUSPEND_IOERR);
                zio_resume_wait(spa);
        }
        dmu_tx_commit(tx);