Remove zvol.c when updating in update-zfs.sh Linux version available.
[zfs.git] / module / zfs / vdev.c
index 3fa677e..bb5024f 100644 (file)
@@ -405,22 +405,26 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
                if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY,
                    &nparity) == 0) {
                        /*
-                        * Currently, we can only support 2 parity devices.
+                        * Currently, we can only support 3 parity devices.
                         */
-                       if (nparity == 0 || nparity > 2)
+                       if (nparity == 0 || nparity > 3)
                                return (EINVAL);
                        /*
-                        * Older versions can only support 1 parity device.
+                        * Previous versions could only support 1 or 2 parity
+                        * device.
                         */
-                       if (nparity == 2 &&
-                           spa_version(spa) < SPA_VERSION_RAID6)
+                       if (nparity > 1 &&
+                           spa_version(spa) < SPA_VERSION_RAIDZ2)
+                               return (ENOTSUP);
+                       if (nparity > 2 &&
+                           spa_version(spa) < SPA_VERSION_RAIDZ3)
                                return (ENOTSUP);
                } else {
                        /*
                         * We require the parity to be specified for SPAs that
                         * support multiple parity levels.
                         */
-                       if (spa_version(spa) >= SPA_VERSION_RAID6)
+                       if (spa_version(spa) >= SPA_VERSION_RAIDZ2)
                                return (EINVAL);
                        /*
                         * Otherwise, we default to 1 parity device for RAID-Z.
@@ -993,6 +997,32 @@ vdev_probe(vdev_t *vd, zio_t *zio)
        return (NULL);
 }
 
+static void
+vdev_open_child(void *arg)
+{
+       vdev_t *vd = arg;
+
+       vd->vdev_open_thread = curthread;
+       vd->vdev_open_error = vdev_open(vd);
+       vd->vdev_open_thread = NULL;
+}
+
+void
+vdev_open_children(vdev_t *vd)
+{
+       taskq_t *tq;
+       int children = vd->vdev_children;
+
+       tq = taskq_create("vdev_open", children, minclsyspri,
+           children, children, TASKQ_PREPOPULATE);
+
+       for (int c = 0; c < children; c++)
+               VERIFY(taskq_dispatch(tq, vdev_open_child, vd->vdev_child[c],
+                   TQ_SLEEP) != NULL);
+
+       taskq_destroy(tq);
+}
+
 /*
  * Prepare a virtual device for access.
  */
@@ -1005,8 +1035,8 @@ vdev_open(vdev_t *vd)
        uint64_t asize, psize;
        uint64_t ashift = 0;
 
-       ASSERT(spa_config_held(spa, SCL_STATE_ALL, RW_WRITER) == SCL_STATE_ALL);
-
+       ASSERT(vd->vdev_open_thread == curthread ||
+           spa_config_held(spa, SCL_STATE_ALL, RW_WRITER) == SCL_STATE_ALL);
        ASSERT(vd->vdev_state == VDEV_STATE_CLOSED ||
            vd->vdev_state == VDEV_STATE_CANT_OPEN ||
            vd->vdev_state == VDEV_STATE_OFFLINE);
@@ -1217,7 +1247,12 @@ vdev_validate(vdev_t *vd)
 
                nvlist_free(label);
 
-               if (spa->spa_load_state == SPA_LOAD_OPEN &&
+               /*
+                * If spa->spa_load_verbatim is true, no need to check the
+                * state of the pool.
+                */
+               if (!spa->spa_load_verbatim &&
+                   spa->spa_load_state == SPA_LOAD_OPEN &&
                    state != POOL_STATE_ACTIVE)
                        return (EBADF);