From 38640550f28c5acd94621f3452fab428df469bdb Mon Sep 17 00:00:00 2001 From: Don Brady Date: Fri, 13 Jan 2017 14:50:22 -0700 Subject: [PATCH] OpenZFS 7743 - per-vdev-zaps init path for upgrade Authored by: Paul Dagnelie Reviewed by: Matt Ahrens Reviewed by: Pavel Zakharov Reviewed by: George Wilson Reviewed by: Don Brady Reviewed-by: Brian Behlendorf Reviewed-by: Joe Stein Ported-by: Don Brady When loading a pool that had been created before the existance of per-vdev zaps, on a system that knows about per-vdev zaps, the per-vdev zaps will not be allocated and initialized. This appears to be because the logic that would have done so, in spa_sync_config_object(), is not reached under normal operation. It is only reached if spa_config_dirty_list is non-empty. The fix is to add another `AVZ_ACTION_` enum that will allow this code to be reached when we detect that we're loading an old pool, even when there are no dirty configs. OpenZFS-issue: https://www.illumos.org/issues/7743 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/e2d29d0 Closes #5582 --- include/sys/spa_impl.h | 3 ++- module/zfs/spa.c | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/sys/spa_impl.h b/include/sys/spa_impl.h index b80764537..5f2a87309 100644 --- a/include/sys/spa_impl.h +++ b/include/sys/spa_impl.h @@ -120,7 +120,8 @@ typedef struct spa_taskqs { typedef enum spa_all_vdev_zap_action { AVZ_ACTION_NONE = 0, AVZ_ACTION_DESTROY, /* Destroy all per-vdev ZAPs and the AVZ. */ - AVZ_ACTION_REBUILD /* Populate the new AVZ, see spa_avz_rebuild */ + AVZ_ACTION_REBUILD, /* Populate the new AVZ, see spa_avz_rebuild */ + AVZ_ACTION_INITIALIZE } spa_avz_action_t; struct spa { diff --git a/module/zfs/spa.c b/module/zfs/spa.c index b4ca3c4d3..73512ddb2 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -2766,10 +2766,14 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config, error = spa_dir_prop(spa, DMU_POOL_VDEV_ZAP_MAP, &spa->spa_all_vdev_zaps); - if (error != ENOENT && error != 0) { + if (error == ENOENT) { + VERIFY(!nvlist_exists(mos_config, + ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS)); + spa->spa_avz_action = AVZ_ACTION_INITIALIZE; + ASSERT0(vdev_count_verify_zaps(spa->spa_root_vdev)); + } else if (error != 0) { return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO)); - } else if (error == 0 && !nvlist_exists(mos_config, - ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS)) { + } else if (!nvlist_exists(mos_config, ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS)) { /* * An older version of ZFS overwrote the sentinel value, so * we have orphaned per-vdev ZAPs in the MOS. Defer their @@ -6135,6 +6139,7 @@ spa_sync_config_object(spa_t *spa, dmu_tx_t *tx) spa_config_enter(spa, SCL_STATE, FTAG, RW_READER); ASSERT(spa->spa_avz_action == AVZ_ACTION_NONE || + spa->spa_avz_action == AVZ_ACTION_INITIALIZE || spa->spa_all_vdev_zaps != 0); if (spa->spa_avz_action == AVZ_ACTION_REBUILD) { -- 2.39.5