From 13473d7f770a78f55e113992ceabe14c29b167c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Tue, 22 Mar 2022 16:51:32 +0300 Subject: [PATCH 1/3] mdbx: preserve (don't upgrade) format-signature during turn to a specified meta-page while recovery. --- src/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core.c b/src/core.c index 3f25c37e7..91d6eb398 100644 --- a/src/core.c +++ b/src/core.c @@ -12618,6 +12618,9 @@ __cold static int __must_check_result mdbx_override_meta( mdbx_assert(env, meta_checktxnid(env, model, true)); if (shape) { mdbx_assert(env, meta_checktxnid(env, shape, true)); + if (env->me_stuck_meta >= 0) + memcpy(&model->mm_magic_and_version, &shape->mm_magic_and_version, + sizeof(model->mm_magic_and_version)); model->mm_extra_flags = shape->mm_extra_flags; model->mm_validator_id = shape->mm_validator_id; model->mm_extra_pagehdr = shape->mm_extra_pagehdr; From ebded939ec7a2d0af7559916ddfd0c585007802a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Tue, 22 Mar 2022 20:40:30 +0300 Subject: [PATCH 2/3] mdbx: add `MDBX_DBG_DONT_UPGRADE` flag. --- mdbx.h | 11 ++++++++--- src/core.c | 9 ++++++--- src/mdbx_chk.c | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/mdbx.h b/mdbx.h index 3844afc5c..1e71f1ada 100644 --- a/mdbx.h +++ b/mdbx.h @@ -864,18 +864,23 @@ enum MDBX_debug_flags_t { MDBX_DBG_JITTER = 4, /** Include or not meta-pages in coredump files. - * May affect performance in \ref MDBX_WRITEMAP mode */ + * \note May affect performance in \ref MDBX_WRITEMAP mode */ MDBX_DBG_DUMP = 8, /** Allow multi-opening environment(s) */ MDBX_DBG_LEGACY_MULTIOPEN = 16, - /** Allow read and write transactions overlapping for the same thread */ + /** Allow read and write transactions overlapping for the same thread. */ MDBX_DBG_LEGACY_OVERLAP = 32, + /** Don't auto-upgrade format signature. + * \note However a new write transactions will use and store + * the last signature regardless this flag */ + MDBX_DBG_DONT_UPGRADE = 64, + #ifdef ENABLE_UBSAN MDBX_DBG_MAX = ((unsigned)MDBX_LOG_MAX) << 16 | - 63 /* avoid UBSAN false-positive trap by a tests */, + 127 /* avoid UBSAN false-positive trap by a tests */, #endif /* ENABLE_UBSAN */ /** for mdbx_setup_debug() only: Don't change current settings */ diff --git a/src/core.c b/src/core.c index 91d6eb398..da3461d1d 100644 --- a/src/core.c +++ b/src/core.c @@ -12278,7 +12278,8 @@ __cold static int mdbx_setup_dxb(MDBX_env *env, const int lck_rc, atomic_store32(&env->me_lck->mti_discarded_tail, bytes2pgno(env, used_aligned2os_bytes), mo_Relaxed); - if ((env->me_flags & MDBX_RDONLY) == 0 && env->me_stuck_meta < 0) { + if ((env->me_flags & MDBX_RDONLY) == 0 && env->me_stuck_meta < 0 && + (mdbx_runtime_flags & MDBX_DBG_DONT_UPGRADE) == 0) { for (int n = 0; n < NUM_METAS; ++n) { MDBX_meta *const pmeta = METAPAGE(env, n); if (unlikely(unaligned_peek_u64(4, &pmeta->mm_magic_and_version) != @@ -12618,7 +12619,8 @@ __cold static int __must_check_result mdbx_override_meta( mdbx_assert(env, meta_checktxnid(env, model, true)); if (shape) { mdbx_assert(env, meta_checktxnid(env, shape, true)); - if (env->me_stuck_meta >= 0) + if (env->me_stuck_meta >= 0 || + (mdbx_runtime_flags & MDBX_DBG_DONT_UPGRADE) != 0) memcpy(&model->mm_magic_and_version, &shape->mm_magic_and_version, sizeof(model->mm_magic_and_version)); model->mm_extra_flags = shape->mm_extra_flags; @@ -20877,7 +20879,8 @@ __cold int mdbx_setup_debug(int loglevel, int flags, MDBX_debug_func *logger) { #if MDBX_DEBUG MDBX_DBG_ASSERT | MDBX_DBG_AUDIT | MDBX_DBG_JITTER | #endif - MDBX_DBG_DUMP | MDBX_DBG_LEGACY_MULTIOPEN | MDBX_DBG_LEGACY_OVERLAP; + MDBX_DBG_DUMP | MDBX_DBG_LEGACY_MULTIOPEN | MDBX_DBG_LEGACY_OVERLAP | + MDBX_DBG_DONT_UPGRADE; mdbx_runtime_flags = (uint8_t)flags; } diff --git a/src/mdbx_chk.c b/src/mdbx_chk.c index 455acb8c5..62dfcd244 100644 --- a/src/mdbx_chk.c +++ b/src/mdbx_chk.c @@ -1226,7 +1226,7 @@ int main(int argc, char *argv[]) { mdbx_setup_debug((verbose < MDBX_LOG_TRACE - 1) ? (MDBX_log_level_t)(verbose + 1) : MDBX_LOG_TRACE, - MDBX_DBG_LEGACY_OVERLAP, logger); + MDBX_DBG_LEGACY_OVERLAP | MDBX_DBG_DONT_UPGRADE, logger); rc = mdbx_env_create(&env); if (rc) { From 75922a87b6e5c936f001168f2380d18b58ea8977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Wed, 23 Mar 2022 00:38:31 +0300 Subject: [PATCH 3/3] mdbx: refine `override_meta()` to preserve format-signature for legacy/zero mod_txnid. --- src/core.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/core.c b/src/core.c index da3461d1d..95a826e8a 100644 --- a/src/core.c +++ b/src/core.c @@ -12618,9 +12618,13 @@ __cold static int __must_check_result mdbx_override_meta( meta_set_txnid(env, model, txnid); mdbx_assert(env, meta_checktxnid(env, model, true)); if (shape) { - mdbx_assert(env, meta_checktxnid(env, shape, true)); - if (env->me_stuck_meta >= 0 || - (mdbx_runtime_flags & MDBX_DBG_DONT_UPGRADE) != 0) + if (txnid && unlikely(!meta_checktxnid(env, shape, false))) { + mdbx_error("bailout overriding meta-%u since model failed " + "freedb/maindb %s-check for txnid #%" PRIaTXN, + target, "pre", constmeta_txnid(env, shape)); + return MDBX_PROBLEM; + } + if (mdbx_runtime_flags & MDBX_DBG_DONT_UPGRADE) memcpy(&model->mm_magic_and_version, &shape->mm_magic_and_version, sizeof(model->mm_magic_and_version)); model->mm_extra_flags = shape->mm_extra_flags; @@ -12631,13 +12635,29 @@ __cold static int __must_check_result mdbx_override_meta( memcpy(&model->mm_canary, &shape->mm_canary, sizeof(model->mm_canary)); memcpy(&model->mm_pages_retired, &shape->mm_pages_retired, sizeof(model->mm_pages_retired)); - mdbx_assert(env, meta_checktxnid(env, model, true)); + if (txnid) { + if ((!model->mm_dbs[FREE_DBI].md_mod_txnid && + model->mm_dbs[FREE_DBI].md_root != P_INVALID) || + (!model->mm_dbs[MAIN_DBI].md_mod_txnid && + model->mm_dbs[MAIN_DBI].md_root != P_INVALID)) + memcpy(&model->mm_magic_and_version, &shape->mm_magic_and_version, + sizeof(model->mm_magic_and_version)); + if (unlikely(!meta_checktxnid(env, model, false))) { + mdbx_error("bailout overriding meta-%u since model failed " + "freedb/maindb %s-check for txnid #%" PRIaTXN, + target, "post", txnid); + return MDBX_PROBLEM; + } + } } unaligned_poke_u64(4, model->mm_datasync_sign, meta_sign(model)); rc = mdbx_validate_meta(env, model, page, target, nullptr); if (unlikely(MDBX_IS_ERROR(rc))) return MDBX_PROBLEM; + if (shape && memcmp(model, shape, sizeof(MDBX_meta)) == 0) + return MDBX_SUCCESS; + #if MDBX_ENABLE_PGOP_STAT env->me_lck->mti_pgop_stat.wops.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */