diff --git a/include/sys/vdev_impl.h b/include/sys/vdev_impl.h index 3c19b9abe9c..84e78f5dbc8 100644 --- a/include/sys/vdev_impl.h +++ b/include/sys/vdev_impl.h @@ -592,6 +592,7 @@ extern boolean_t vdev_log_state_valid(vdev_t *vd); extern int vdev_load(vdev_t *vd); extern int vdev_dtl_load(vdev_t *vd); extern void vdev_sync(vdev_t *vd, uint64_t txg); +extern void vdev_sync_dispatch(vdev_t *vd, uint64_t txg); extern void vdev_sync_done(vdev_t *vd, uint64_t txg); extern void vdev_dirty(vdev_t *vd, int flags, void *arg, uint64_t txg); extern void vdev_dirty_leaves(vdev_t *vd, int flags, uint64_t txg); diff --git a/module/zfs/spa.c b/module/zfs/spa.c index ec93ce97433..c6ae91b8d9e 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -11019,6 +11019,10 @@ spa_sync(spa_t *spa, uint64_t txg) ASSERT0(spa->spa_vdev_removal->svr_bytes_done[txg & TXG_MASK]); } + for (vd = txg_list_head(&spa->spa_vdev_txg_list, TXG_CLEAN(txg)); vd; + vd = txg_list_next(&spa->spa_vdev_txg_list, vd, TXG_CLEAN(txg))) + vdev_sync_dispatch(vd, txg); + spa_sync_rewrite_vdev_config(spa, tx); dmu_tx_commit(tx); @@ -11043,9 +11047,6 @@ spa_sync(spa_t *spa, uint64_t txg) dsl_pool_sync_done(dp, txg); - /* - * Update usable space statistics. - */ while ((vd = txg_list_remove(&spa->spa_vdev_txg_list, TXG_CLEAN(txg))) != NULL) vdev_sync_done(vd, txg); diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c index 211adae0968..53a3b927d52 100644 --- a/module/zfs/vdev.c +++ b/module/zfs/vdev.c @@ -4246,17 +4246,39 @@ vdev_remove_empty_log(vdev_t *vd, uint64_t txg) dmu_tx_commit(tx); } +static void +metaslab_sync_done_task(void *arg) +{ + metaslab_t *msp = arg; + spa_t *spa = msp->ms_group->mg_vd->vdev_spa; + metaslab_sync_done(msp, spa_syncing_txg(spa)); +} + +void +vdev_sync_dispatch(vdev_t *vd, uint64_t txg) +{ + spa_t *spa = vd->vdev_spa; + + ASSERT(vdev_is_concrete(vd)); + + for (metaslab_t *msp = txg_list_head(&vd->vdev_ms_list, TXG_CLEAN(txg)); + msp; msp = txg_list_next(&vd->vdev_ms_list, msp, TXG_CLEAN(txg))) { + (void) taskq_dispatch(spa->spa_sync_tq, + metaslab_sync_done_task, msp, TQ_SLEEP); + } +} + void vdev_sync_done(vdev_t *vd, uint64_t txg) { - metaslab_t *msp; boolean_t reassess = !txg_list_empty(&vd->vdev_ms_list, TXG_CLEAN(txg)); ASSERT(vdev_is_concrete(vd)); - while ((msp = txg_list_remove(&vd->vdev_ms_list, TXG_CLEAN(txg))) - != NULL) - metaslab_sync_done(msp, txg); + taskq_wait(vd->vdev_spa->spa_sync_tq); + + while (txg_list_remove(&vd->vdev_ms_list, TXG_CLEAN(txg)) != NULL) + ; if (reassess) { metaslab_sync_reassess(vd->vdev_mg);