diff options
author | George Wilson <[email protected]> | 2017-04-07 13:50:18 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2017-04-09 16:12:35 -0700 |
commit | 3b7f360c9606079c518829c5bd82fe8f8a89e3c0 (patch) | |
tree | e5dad1e8833519127ebee8597ea8f1ec746fbb2b /module/zfs/metaslab.c | |
parent | 4c3c6b6c73e31c789a2c0ce2a70912c077f15421 (diff) |
OpenZFS 8023 - Panic destroying a metaslab deferred range tree
Authored by: George Wilson <[email protected]>
Approved by: Dan McDonald <[email protected]>
Reviewed by: Brad Lewis <[email protected]>
Reviewed by: Matt Ahrens <[email protected]>
Reviewed by: Dan Kimmel <[email protected]>
Reviewed by: Saso Kiselkov <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: George Melikov <[email protected]>
Ported-by: Giuseppe Di Natale <[email protected]>
We don't want to dirty any data when we're in the final txgs of the pool
export logic. This change introduces checks to make sure that no data is
dirtied after a certain point. It also addresses the culprit of this
specific bug – the space map cannot be upgraded when we're in final
stages of pool export. If we encounter a space map that wants to be
upgraded in this phase, then we simply ignore the request as it will get
retried the next time we set the fragmentation metric on that metaslab.
OpenZFS-issue: https://www.illumos.org/issues/8023
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/2ef00f5
Closes #5991
Diffstat (limited to 'module/zfs/metaslab.c')
-rw-r--r-- | module/zfs/metaslab.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/module/zfs/metaslab.c b/module/zfs/metaslab.c index 3fd7f9049..5e413c065 100644 --- a/module/zfs/metaslab.c +++ b/module/zfs/metaslab.c @@ -1582,15 +1582,22 @@ metaslab_set_fragmentation(metaslab_t *msp) * so that we upgrade next time we encounter it. */ if (msp->ms_sm->sm_dbuf->db_size != sizeof (space_map_phys_t)) { + uint64_t txg = spa_syncing_txg(spa); vdev_t *vd = msp->ms_group->mg_vd; - if (spa_writeable(vd->vdev_spa)) { - uint64_t txg = spa_syncing_txg(spa); - + /* + * If we've reached the final dirty txg, then we must + * be shutting down the pool. We don't want to dirty + * any data past this point so skip setting the condense + * flag. We can retry this action the next time the pool + * is imported. + */ + if (spa_writeable(spa) && txg < spa_final_dirty_txg(spa)) { msp->ms_condense_wanted = B_TRUE; vdev_dirty(vd, VDD_METASLAB, msp, txg + 1); spa_dbgmsg(spa, "txg %llu, requesting force condense: " - "msp %p, vd %p", txg, msp, vd); + "ms_id %llu, vdev_id %llu", txg, msp->ms_id, + vd->vdev_id); } msp->ms_fragmentation = ZFS_FRAG_INVALID; return; @@ -2217,13 +2224,17 @@ metaslab_sync(metaslab_t *msp, uint64_t txg) /* * Normally, we don't want to process a metaslab if there * are no allocations or frees to perform. However, if the metaslab - * is being forced to condense we need to let it through. + * is being forced to condense and it's loaded, we need to let it + * through. */ if (range_tree_space(alloctree) == 0 && range_tree_space(msp->ms_freeingtree) == 0 && - !msp->ms_condense_wanted) + !(msp->ms_loaded && msp->ms_condense_wanted)) return; + + VERIFY(txg <= spa_final_dirty_txg(spa)); + /* * The only state that can actually be changing concurrently with * metaslab_sync() is the metaslab's ms_tree. No other thread can |