From: Brian Behlendorf Date: Tue, 12 Mar 2019 17:39:47 +0000 (-0700) Subject: Fix vdev_initialize_restart / removal race X-Git-Tag: zfs-0.8.0-rc4~80 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dd785b5b86bbb7ebbfe1d22668f3dd27c5704994;p=zfs Fix vdev_initialize_restart / removal race Resolve a vdev_initialize crash uncovered by ztest. Similar to when starting a new initialization verify that a removal is not in progress. Additionally, do not restart when the thread already exists. This check is now congruent with the POOL_INITIALIZE_DO handling in spa_vdev_initialize_impl(). Reviewed-by: Tom Caputi Signed-off-by: Brian Behlendorf Closes #8477 --- diff --git a/module/zfs/vdev_initialize.c b/module/zfs/vdev_initialize.c index bec89a28e..bca2db7a4 100644 --- a/module/zfs/vdev_initialize.c +++ b/module/zfs/vdev_initialize.c @@ -68,7 +68,7 @@ vdev_initialize_zap_update_sync(void *arg, dmu_tx_t *tx) * We pass in the guid instead of the vdev_t since the vdev may * have been freed prior to the sync task being processed. This * happens when a vdev is detached as we call spa_config_vdev_exit(), - * stop the intializing thread, schedule the sync task, and free + * stop the initializing thread, schedule the sync task, and free * the vdev. Later when the scheduled sync task is invoked, it would * find that the vdev has been freed. */ @@ -838,7 +838,9 @@ vdev_initialize_restart(vdev_t *vd) /* load progress for reporting, but don't resume */ VERIFY0(vdev_initialize_load(vd)); } else if (vd->vdev_initialize_state == - VDEV_INITIALIZE_ACTIVE && vdev_writeable(vd)) { + VDEV_INITIALIZE_ACTIVE && vdev_writeable(vd) && + !vd->vdev_top->vdev_removing && + vd->vdev_initialize_thread == NULL) { vdev_initialize(vd); }