]> git.proxmox.com Git - mirror_zfs.git/commitdiff
OpenZFS 7743 - per-vdev-zaps init path for upgrade
authorDon Brady <don.brady@intel.com>
Fri, 13 Jan 2017 21:50:22 +0000 (14:50 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 13 Jan 2017 21:50:22 +0000 (13:50 -0800)
Authored by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Matt Ahrens <mahrens@delphix.com>
Reviewed by: Pavel Zakharov <pavel.zakharov@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Don Brady <don.brady@intel.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Joe Stein <jas14@cs.brown.edu>
Ported-by: Don Brady <don.brady@intel.com>
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
module/zfs/spa.c

index b807645373c90812dc7762cdca925d7d654b130f..5f2a8730903b1b31789edad439322b5ca753daa3 100644 (file)
@@ -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 {
index b4ca3c4d3e421f84f20116cc631ae068082dbe34..73512ddb28808522f999ec4970ed5d84499ce0bb 100644 (file)
@@ -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) {