diff options
Diffstat (limited to 'module/zfs/vdev.c')
-rw-r--r-- | module/zfs/vdev.c | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c index f305da6f5..018e48c38 100644 --- a/module/zfs/vdev.c +++ b/module/zfs/vdev.c @@ -1725,6 +1725,14 @@ vdev_probe(vdev_t *vd, zio_t *zio) } static void +vdev_load_child(void *arg) +{ + vdev_t *vd = arg; + + vd->vdev_load_error = vdev_load(vd); +} + +static void vdev_open_child(void *arg) { vdev_t *vd = arg; @@ -3350,18 +3358,46 @@ vdev_checkpoint_sm_object(vdev_t *vd, uint64_t *sm_obj) int vdev_load(vdev_t *vd) { + int children = vd->vdev_children; int error = 0; + taskq_t *tq = NULL; + + /* + * It's only worthwhile to use the taskq for the root vdev, because the + * slow part is metaslab_init, and that only happens for top-level + * vdevs. + */ + if (vd->vdev_ops == &vdev_root_ops && vd->vdev_children > 0) { + tq = taskq_create("vdev_load", children, minclsyspri, + children, children, TASKQ_PREPOPULATE); + } /* * Recursively load all children. */ for (int c = 0; c < vd->vdev_children; c++) { - error = vdev_load(vd->vdev_child[c]); - if (error != 0) { - return (error); + vdev_t *cvd = vd->vdev_child[c]; + + if (tq == NULL || vdev_uses_zvols(cvd)) { + cvd->vdev_load_error = vdev_load(cvd); + } else { + VERIFY(taskq_dispatch(tq, vdev_load_child, + cvd, TQ_SLEEP) != TASKQID_INVALID); } } + if (tq != NULL) { + taskq_wait(tq); + taskq_destroy(tq); + } + + for (int c = 0; c < vd->vdev_children; c++) { + int error = vd->vdev_child[c]->vdev_load_error; + + if (error != 0) + return (error); + } + vdev_set_deflate_ratio(vd); /* |