diff --git a/include/sys/uberblock_impl.h b/include/sys/uberblock_impl.h index 91699e65131a..8a8f1d6a3f01 100644 --- a/include/sys/uberblock_impl.h +++ b/include/sys/uberblock_impl.h @@ -136,6 +136,20 @@ struct uberblock { * the ZIL block is not allocated [see uses of spa_min_claim_txg()]. */ uint64_t ub_checkpoint_txg; + + /* + * The stats below are part of the MOS dsl_dir and + * are typically written out in later passes of spa_sync + * when we are overwriting blocks. + * + * Since object-based pools do not allow block overwrites, + * store these stats temporarily in the uberblock when + * we finalize the txg. These stats will be synced out to + * the dsl_dir in a subsequent txg when the dsl_dir is dirtied. + */ + uint64_t ub_dp_mos_used_delta; + uint64_t ub_dp_mos_compressed_delta; + uint64_t ub_dp_mos_uncompressed_delta; }; #ifdef __cplusplus diff --git a/module/os/linux/zfs/vdev_object_store.c b/module/os/linux/zfs/vdev_object_store.c index 7dcc9d29a5de..902364fc9ee2 100644 --- a/module/os/linux/zfs/vdev_object_store.c +++ b/module/os/linux/zfs/vdev_object_store.c @@ -1293,8 +1293,19 @@ agent_reader(void *arg) int err = nvlist_lookup_uint8_array(nv, AGENT_UBERBLOCK, &arr, &len); if (err == 0) { - ASSERT3U(len, ==, sizeof (uberblock_t)); + ASSERT3U(len, <=, sizeof (uberblock_t)); bcopy(arr, &vos->vos_uberblock, len); + + /* + * We may be opening an uberblock from a pool + * with an older on-disk format. To handle this, + * we just zero out any uberblock members that + * did not exist when the uberblock was written. + */ + if (len < sizeof (uberblock_t)) { + bzero(&vos->vos_uberblock + len, + sizeof (uberblock_t) - len); + } VERIFY0(nvlist_lookup_uint8_array(nv, AGENT_CONFIG, &arr, &len)); vos->vos_config = fnvlist_unpack((char *)arr, len); diff --git a/module/zfs/spa.c b/module/zfs/spa.c index 7c0af25f51c4..f93ba70e081b 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -9184,6 +9184,36 @@ spa_sync_condense_indirect(spa_t *spa, dmu_tx_t *tx) } } +static void +spa_sync_restore_mos_stats(spa_t *spa) +{ + dsl_pool_t *dp = spa->spa_dsl_pool; + uberblock_t *ub = &spa->spa_uberblock; + + ASSERT0(dp->dp_mos_used_delta); + ASSERT0(dp->dp_mos_compressed_delta); + ASSERT0(dp->dp_mos_uncompressed_delta); + dp->dp_mos_used_delta = ub->ub_dp_mos_used_delta; + dp->dp_mos_compressed_delta = ub->ub_dp_mos_compressed_delta; + dp->dp_mos_uncompressed_delta = ub->ub_dp_mos_uncompressed_delta; +} + +static void +spa_sync_save_mos_stats(spa_t *spa) +{ + dsl_pool_t *dp = spa->spa_dsl_pool; + uberblock_t *ub = &spa->spa_uberblock; + + ub->ub_dp_mos_used_delta = dp->dp_mos_used_delta; + ub->ub_dp_mos_compressed_delta = dp->dp_mos_compressed_delta; + ub->ub_dp_mos_uncompressed_delta = dp->dp_mos_uncompressed_delta; + + dp->dp_mos_used_delta = 0; + dp->dp_mos_compressed_delta = 0; + dp->dp_mos_uncompressed_delta = 0; +} + + static void spa_sync_iterate_to_convergence(spa_t *spa, dmu_tx_t *tx) { @@ -9192,6 +9222,10 @@ spa_sync_iterate_to_convergence(spa_t *spa, dmu_tx_t *tx) uint64_t txg = tx->tx_txg; bplist_t *free_bpl = &spa->spa_free_bplist[txg & TXG_MASK]; + if (spa_is_object_based(spa)) { + spa_sync_restore_mos_stats(spa); + } + do { int pass = ++spa->spa_sync_pass; @@ -9261,6 +9295,11 @@ spa_sync_iterate_to_convergence(spa_t *spa, dmu_tx_t *tx) spa_sync_deferred_frees(spa, tx); } while (dmu_objset_is_dirty(mos, txg)); + + if (spa_is_object_based(spa)) { + spa_sync_save_mos_stats(spa); + } + } /* @@ -9504,6 +9543,15 @@ spa_sync(spa_t *spa, uint64_t txg) spa->spa_sync_pass = 0; + /* + * The mos stats should have been written out this txg, + * so verify that they are now zero indicating that any + * updates have been persisted to the pool. + */ + VERIFY0(dp->dp_mos_used_delta); + VERIFY0(dp->dp_mos_compressed_delta); + VERIFY0(dp->dp_mos_uncompressed_delta); + /* * Update the last synced uberblock here. We want to do this at * the end of spa_sync() so that consumers of spa_last_synced_txg() diff --git a/tests/runfiles/object_store.run b/tests/runfiles/object_store.run index 79ea0f0a3ca2..ea964c4534d6 100644 --- a/tests/runfiles/object_store.run +++ b/tests/runfiles/object_store.run @@ -107,12 +107,6 @@ tags = ['functional', 'cli_root', 'zfs_change-key'] # ------------------------------------------------------------- # TODO: Add the following tests back after relevant bug fixes. # zpool_create_007_neg - DOSE-608 -# zpool_create_018_pos - DOSE-550 -# zpool_create_encrypted - DOSE-550 -# zpool_create_features_002_pos - DOSE-550 -# zpool_create_features_003_pos - DOSE-550 -# zpool_create_features_006_pos - DOSE-550 -# zpool_create_features_009_pos - DOSE-550 # zpool_create_024_pos - DOSE-568 # ------------------------------------------------------------- # TODO: zpool_create_003_pos fails because of DOSE-545. Its not creating a @@ -124,15 +118,17 @@ tests = ['zpool_create_001_pos', 'zpool_create_002_pos', 'zpool_create_006_pos', 'zpool_create_008_pos', 'zpool_create_009_neg', 'zpool_create_010_neg', 'zpool_create_011_neg', 'zpool_create_012_neg', 'zpool_create_014_neg', 'zpool_create_015_neg', - 'zpool_create_017_neg', 'zpool_create_019_pos', + 'zpool_create_017_neg', 'zpool_create_018_pos', 'zpool_create_019_pos', 'zpool_create_020_pos', 'zpool_create_021_pos', 'zpool_create_022_pos', - 'zpool_create_023_neg', 'zpool_create_crypt_combos', + 'zpool_create_023_neg', 'zpool_create_encrypted', + 'zpool_create_crypt_combos', 'zpool_create_draid_001_pos', 'zpool_create_draid_002_pos', 'zpool_create_draid_003_pos', 'zpool_create_draid_004_pos', - 'zpool_create_features_001_pos', 'zpool_create_features_004_neg', - 'zpool_create_features_005_pos', + 'zpool_create_features_001_pos', 'zpool_create_features_002_pos', + 'zpool_create_features_003_pos', 'zpool_create_features_004_neg', + 'zpool_create_features_005_pos', 'zpool_create_features_006_pos', 'zpool_create_features_007_pos', 'zpool_create_features_008_pos', - 'create-o_ashift', + 'zpool_create_features_009_pos', 'create-o_ashift', 'zpool_create_tempname', 'zpool_create_dryrun_output'] tags = ['functional', 'cli_root', 'zpool_create']