Add AUTHORS to master branch
[zfs.git] / module / zfs / spa_misc.c
index 36046e6..8150ac9 100644 (file)
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -230,7 +230,7 @@ static kmutex_t spa_l2cache_lock;
 static avl_tree_t spa_l2cache_avl;
 
 kmem_cache_t *spa_buffer_pool;
-int spa_mode;
+int spa_mode_global;
 
 #ifdef ZFS_DEBUG
 /* Everything except dprintf is on by default in debug builds */
@@ -310,8 +310,12 @@ spa_config_tryenter(spa_t *spa, int locks, void *tag, krw_t rw)
 void
 spa_config_enter(spa_t *spa, int locks, void *tag, krw_t rw)
 {
+       int wlocks_held = 0;
+
        for (int i = 0; i < SCL_LOCKS; i++) {
                spa_config_lock_t *scl = &spa->spa_config_lock[i];
+               if (scl->scl_writer == curthread)
+                       wlocks_held |= (1 << i);
                if (!(locks & (1 << i)))
                        continue;
                mutex_enter(&scl->scl_lock);
@@ -331,6 +335,7 @@ spa_config_enter(spa_t *spa, int locks, void *tag, krw_t rw)
                (void) refcount_add(&scl->scl_count, tag);
                mutex_exit(&scl->scl_lock);
        }
+       ASSERT(wlocks_held <= locks);
 }
 
 void
@@ -425,7 +430,6 @@ spa_add(const char *name, const char *altroot)
        spa = kmem_zalloc(sizeof (spa_t), KM_SLEEP);
 
        mutex_init(&spa->spa_async_lock, NULL, MUTEX_DEFAULT, NULL);
-       mutex_init(&spa->spa_async_root_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_scrub_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_errlog_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&spa->spa_errlist_lock, NULL, MUTEX_DEFAULT, NULL);
@@ -434,7 +438,6 @@ spa_add(const char *name, const char *altroot)
        mutex_init(&spa->spa_props_lock, NULL, MUTEX_DEFAULT, NULL);
 
        cv_init(&spa->spa_async_cv, NULL, CV_DEFAULT, NULL);
-       cv_init(&spa->spa_async_root_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);
 
@@ -508,12 +511,10 @@ spa_remove(spa_t *spa)
        spa_config_lock_destroy(spa);
 
        cv_destroy(&spa->spa_async_cv);
-       cv_destroy(&spa->spa_async_root_cv);
        cv_destroy(&spa->spa_scrub_io_cv);
        cv_destroy(&spa->spa_suspend_cv);
 
        mutex_destroy(&spa->spa_async_lock);
-       mutex_destroy(&spa->spa_async_root_lock);
        mutex_destroy(&spa->spa_scrub_lock);
        mutex_destroy(&spa->spa_errlog_lock);
        mutex_destroy(&spa->spa_errlist_lock);
@@ -880,8 +881,10 @@ spa_vdev_exit(spa_t *spa, vdev_t *vd, uint64_t txg, int error)
                txg_wait_synced(spa->spa_dsl_pool, txg);
 
        if (vd != NULL) {
-               ASSERT(!vd->vdev_detached || vd->vdev_dtl.smo_object == 0);
+               ASSERT(!vd->vdev_detached || vd->vdev_dtl_smo.smo_object == 0);
+               spa_config_enter(spa, SCL_ALL, spa, RW_WRITER);
                vdev_free(vd);
+               spa_config_exit(spa, SCL_ALL, spa);
        }
 
        /*
@@ -912,6 +915,15 @@ spa_vdev_state_exit(spa_t *spa, vdev_t *vd, int error)
 
        spa_config_exit(spa, SCL_STATE_ALL, spa);
 
+       /*
+        * If anything changed, wait for it to sync.  This ensures that,
+        * from the system administrator's perspective, zpool(1M) commands
+        * are synchronous.  This is important for things like zpool offline:
+        * when the command completes, you expect no further I/O from ZFS.
+        */
+       if (vd != NULL)
+               txg_wait_synced(spa->spa_dsl_pool, 0);
+
        return (error);
 }
 
@@ -1351,7 +1363,7 @@ spa_init(int mode)
        avl_create(&spa_l2cache_avl, spa_l2cache_compare, sizeof (spa_aux_t),
            offsetof(spa_aux_t, aux_avl));
 
-       spa_mode = mode;
+       spa_mode_global = mode;
 
        refcount_init();
        unique_init();
@@ -1408,3 +1420,15 @@ spa_is_root(spa_t *spa)
 {
        return (spa->spa_is_root);
 }
+
+boolean_t
+spa_writeable(spa_t *spa)
+{
+       return (!!(spa->spa_mode & FWRITE));
+}
+
+int
+spa_mode(spa_t *spa)
+{
+       return (spa->spa_mode);
+}