]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/vdev.c
OpenZFS 9102 - zfs should be able to initialize storage devices
[mirror_zfs.git] / module / zfs / vdev.c
index 8273e79079f147c249725a6557ca0beb2116c575..f808f8ee78b93ec2627688b1ab8133b06c94f29a 100644 (file)
@@ -50,6 +50,7 @@
 #include <sys/zil.h>
 #include <sys/dsl_scan.h>
 #include <sys/abd.h>
+#include <sys/vdev_initialize.h>
 #include <sys/zvol.h>
 #include <sys/zfs_ratelimit.h>
 
@@ -212,6 +213,14 @@ vdev_getops(const char *type)
        return (ops);
 }
 
+/* ARGSUSED */
+void
+vdev_default_xlate(vdev_t *vd, const range_seg_t *in, range_seg_t *res)
+{
+       res->rs_start = in->rs_start;
+       res->rs_end = in->rs_end;
+}
+
 /*
  * Derive the enumerated alloction bias from string input.
  * String origin is either the per-vdev zap or zpool(1M).
@@ -526,6 +535,10 @@ vdev_alloc_common(spa_t *spa, uint_t id, uint64_t guid, vdev_ops_t *ops)
        mutex_init(&vd->vdev_probe_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&vd->vdev_queue_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&vd->vdev_scan_io_queue_lock, NULL, MUTEX_DEFAULT, NULL);
+       mutex_init(&vd->vdev_initialize_lock, NULL, MUTEX_DEFAULT, NULL);
+       mutex_init(&vd->vdev_initialize_io_lock, NULL, MUTEX_DEFAULT, NULL);
+       cv_init(&vd->vdev_initialize_cv, NULL, CV_DEFAULT, NULL);
+       cv_init(&vd->vdev_initialize_io_cv, NULL, CV_DEFAULT, NULL);
 
        for (int t = 0; t < DTL_TYPES; t++) {
                vd->vdev_dtl[t] = range_tree_create(NULL, NULL);
@@ -850,6 +863,7 @@ void
 vdev_free(vdev_t *vd)
 {
        spa_t *spa = vd->vdev_spa;
+       ASSERT3P(vd->vdev_initialize_thread, ==, NULL);
 
        /*
         * Scan queues are normally destroyed at the end of a scan. If the
@@ -880,6 +894,7 @@ vdev_free(vdev_t *vd)
 
        ASSERT(vd->vdev_child == NULL);
        ASSERT(vd->vdev_guid_sum == vd->vdev_guid);
+       ASSERT(vd->vdev_initialize_thread == NULL);
 
        /*
         * Discard allocation state.
@@ -957,6 +972,10 @@ vdev_free(vdev_t *vd)
        mutex_destroy(&vd->vdev_stat_lock);
        mutex_destroy(&vd->vdev_probe_lock);
        mutex_destroy(&vd->vdev_scan_io_queue_lock);
+       mutex_destroy(&vd->vdev_initialize_lock);
+       mutex_destroy(&vd->vdev_initialize_io_lock);
+       cv_destroy(&vd->vdev_initialize_io_cv);
+       cv_destroy(&vd->vdev_initialize_cv);
 
        zfs_ratelimit_fini(&vd->vdev_delay_rl);
        zfs_ratelimit_fini(&vd->vdev_checksum_rl);
@@ -3207,7 +3226,8 @@ vdev_sync_done(vdev_t *vd, uint64_t txg)
 
        ASSERT(vdev_is_concrete(vd));
 
-       while ((msp = txg_list_remove(&vd->vdev_ms_list, TXG_CLEAN(txg))))
+       while ((msp = txg_list_remove(&vd->vdev_ms_list, TXG_CLEAN(txg)))
+           != NULL)
                metaslab_sync_done(msp, txg);
 
        if (reassess)
@@ -3458,6 +3478,15 @@ vdev_online(spa_t *spa, uint64_t guid, uint64_t flags, vdev_state_t *newstate)
                spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE);
        }
 
+       /* Restart initializing if necessary */
+       mutex_enter(&vd->vdev_initialize_lock);
+       if (vdev_writeable(vd) &&
+           vd->vdev_initialize_thread == NULL &&
+           vd->vdev_initialize_state == VDEV_INITIALIZE_ACTIVE) {
+               (void) vdev_initialize(vd);
+       }
+       mutex_exit(&vd->vdev_initialize_lock);
+
        if (wasoffline ||
            (oldstate < VDEV_STATE_DEGRADED &&
            vd->vdev_state >= VDEV_STATE_DEGRADED))
@@ -3848,9 +3877,22 @@ vdev_get_stats_ex(vdev_t *vd, vdev_stat_t *vs, vdev_stat_ex_t *vsx)
                vs->vs_timestamp = gethrtime() - vs->vs_timestamp;
                vs->vs_state = vd->vdev_state;
                vs->vs_rsize = vdev_get_min_asize(vd);
-               if (vd->vdev_ops->vdev_op_leaf)
+               if (vd->vdev_ops->vdev_op_leaf) {
                        vs->vs_rsize += VDEV_LABEL_START_SIZE +
                            VDEV_LABEL_END_SIZE;
+                       /*
+                        * Report intializing progress. Since we don't
+                        * have the initializing locks held, this is only
+                        * an estimate (although a fairly accurate one).
+                        */
+                       vs->vs_initialize_bytes_done =
+                           vd->vdev_initialize_bytes_done;
+                       vs->vs_initialize_bytes_est =
+                           vd->vdev_initialize_bytes_est;
+                       vs->vs_initialize_state = vd->vdev_initialize_state;
+                       vs->vs_initialize_action_time =
+                           vd->vdev_initialize_action_time;
+               }
                /*
                 * Report expandable space on top-level, non-auxillary devices
                 * only. The expandable space is reported in terms of metaslab