From: Serapheim Dimitropoulos Date: Tue, 15 May 2018 17:43:25 +0000 (-0700) Subject: OpenZFS 9690 - metaslab of vdev with no space maps was flushed during removal X-Git-Tag: zfs-0.8.0-rc2~47 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ee900344f2f81cd3cc8dda95e8e8e41497d58001;p=zfs OpenZFS 9690 - metaslab of vdev with no space maps was flushed during removal Authored by: Serapheim Dimitropoulos Reviewed by: Matt Ahrens Reviewed by: Brad Lewis Reviewed by: George Melikov Approved by: Robert Mustacchi Ported-by: Brian Behlendorf OpenZFS-issue: https://www.illumos.org/issues/9690 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/4e75ba6826 Closes #8039 --- diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c index 1521acc40..9a7f5e011 100644 --- a/module/zfs/vdev.c +++ b/module/zfs/vdev.c @@ -3129,11 +3129,11 @@ vdev_destroy_spacemaps(vdev_t *vd, dmu_tx_t *tx) } static void -vdev_remove_empty(vdev_t *vd, uint64_t txg) +vdev_remove_empty_log(vdev_t *vd, uint64_t txg) { spa_t *spa = vd->vdev_spa; - dmu_tx_t *tx; + ASSERT(vd->vdev_islog); ASSERT(vd == vd->vdev_top); ASSERT3U(txg, ==, spa_syncing_txg(spa)); @@ -3178,13 +3178,14 @@ vdev_remove_empty(vdev_t *vd, uint64_t txg) ASSERT0(mg->mg_histogram[i]); } - tx = dmu_tx_create_assigned(spa_get_dsl(spa), txg); - vdev_destroy_spacemaps(vd, tx); + dmu_tx_t *tx = dmu_tx_create_assigned(spa_get_dsl(spa), txg); - if (vd->vdev_islog && vd->vdev_top_zap != 0) { + vdev_destroy_spacemaps(vd, tx); + if (vd->vdev_top_zap != 0) { vdev_destroy_unlink_zap(vd, vd->vdev_top_zap, tx); vd->vdev_top_zap = 0; } + dmu_tx_commit(tx); } @@ -3255,14 +3256,11 @@ vdev_sync(vdev_t *vd, uint64_t txg) vdev_dtl_sync(lvd, txg); /* - * Remove the metadata associated with this vdev once it's empty. - * Note that this is typically used for log/cache device removal; - * we don't empty toplevel vdevs when removing them. But if - * a toplevel happens to be emptied, this is not harmful. + * If this is an empty log device being removed, destroy the + * metadata associated with it. */ - if (vd->vdev_stat.vs_alloc == 0 && vd->vdev_removing) { - vdev_remove_empty(vd, txg); - } + if (vd->vdev_islog && vd->vdev_stat.vs_alloc == 0 && vd->vdev_removing) + vdev_remove_empty_log(vd, txg); (void) txg_list_add(&spa->spa_vdev_txg_list, vd, TXG_CLEAN(txg)); }