]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/spa.c
Illumos 5056 - ZFS deadlock on db_mtx and dn_holds
[mirror_zfs.git] / module / zfs / spa.c
index 121883bfa61d9d9ae0792fe0fd9ff5c08d1ed171..376f5ae13db3433aa5a5b5ddf4eac265207308d3 100644 (file)
@@ -23,6 +23,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2013 by Delphix. All rights reserved.
  * Copyright (c) 2013, 2014, Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
  */
 
 /*
@@ -1095,6 +1096,8 @@ spa_activate(spa_t *spa, int mode)
 
        list_create(&spa->spa_config_dirty_list, sizeof (vdev_t),
            offsetof(vdev_t, vdev_config_dirty_node));
+       list_create(&spa->spa_evicting_os_list, sizeof (objset_t),
+           offsetof(objset_t, os_evicting_node));
        list_create(&spa->spa_state_dirty_list, sizeof (vdev_t),
            offsetof(vdev_t, vdev_state_dirty_node));
 
@@ -1123,9 +1126,12 @@ spa_deactivate(spa_t *spa)
        ASSERT(spa->spa_async_zio_root == NULL);
        ASSERT(spa->spa_state != POOL_STATE_UNINITIALIZED);
 
+       spa_evicting_os_wait(spa);
+
        txg_list_destroy(&spa->spa_vdev_txg_list);
 
        list_destroy(&spa->spa_config_dirty_list);
+       list_destroy(&spa->spa_evicting_os_list);
        list_destroy(&spa->spa_state_dirty_list);
 
        taskq_cancel_id(system_taskq, spa->spa_deadman_tqid);
@@ -2136,6 +2142,11 @@ spa_load(spa_t *spa, spa_load_state_t state, spa_import_type_t type,
                    mosconfig, &ereport);
        }
 
+       /*
+        * Don't count references from objsets that are already closed
+        * and are making their way through the eviction process.
+        */
+       spa_evicting_os_wait(spa);
        spa->spa_minref = refcount_count(&spa->spa_refcount);
        if (error) {
                if (error != EEXIST) {
@@ -3775,6 +3786,11 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
 
        spa_history_log_version(spa, "create");
 
+       /*
+        * Don't count references from objsets that are already closed
+        * and are making their way through the eviction process.
+        */
+       spa_evicting_os_wait(spa);
        spa->spa_minref = refcount_count(&spa->spa_refcount);
 
        mutex_exit(&spa_namespace_lock);
@@ -4314,8 +4330,10 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig,
         * modify its state.  Objsets may be open only because they're dirty,
         * so we have to force it to sync before checking spa_refcnt.
         */
-       if (spa->spa_sync_on)
+       if (spa->spa_sync_on) {
                txg_wait_synced(spa->spa_dsl_pool, 0);
+               spa_evicting_os_wait(spa);
+       }
 
        /*
         * A pool cannot be exported or destroyed if there are active