From 5e714ed946b42be7d61d847cfde3e2cf7db70164 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: Mon, 3 Mar 2025 01:48:36 +0300 Subject: [PATCH] =?UTF-8?q?mdbx:=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=BA=D0=B0=20`env=5Fowned=5Fwrtxn()`=20=D0=B8=20=D0=BC?= =?UTF-8?q?=D0=B5=D1=81=D1=82=20=D0=B5=D1=91=20=D0=B2=D1=8B=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=20(backport).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Цель в том чтобы избавить от коллизии блокировки возникающей внутри dxb_sanitize_tail() при использовании Valgrind/ASAN, а также упросить код. --- src/api-cold.c | 2 +- src/api-env.c | 27 ++++++++++++--------------- src/api-opts.c | 2 +- src/dxb.c | 2 +- src/env.c | 21 +++++++++++++-------- src/proto.h | 2 +- 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/api-cold.c b/src/api-cold.c index 1d124852..8a8c8588 100644 --- a/src/api-cold.c +++ b/src/api-cold.c @@ -342,7 +342,7 @@ __cold int mdbx_env_set_flags(MDBX_env *env, MDBX_env_flags_t flags, bool onoff) if (unlikely(env->flags & MDBX_RDONLY)) return LOG_IFERR(MDBX_EACCESS); - const bool lock_needed = (env->flags & ENV_ACTIVE) && !env_txn0_owned(env); + const bool lock_needed = (env->flags & ENV_ACTIVE) && !env_owned_wrtxn(env); bool should_unlock = false; if (lock_needed) { rc = lck_txn_lock(env, false); diff --git a/src/api-env.c b/src/api-env.c index 6a9a719b..2bfbdeb2 100644 --- a/src/api-env.c +++ b/src/api-env.c @@ -958,8 +958,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si if (unlikely(rc != MDBX_SUCCESS)) return LOG_IFERR(rc); - const bool txn0_owned = env->basal_txn && env_txn0_owned(env); - const bool inside_txn = txn0_owned && env->txn; + MDBX_txn *const txn_owned = env_owned_wrtxn(env); bool should_unlock = false; #if MDBX_DEBUG && 0 /* минимальные шаги для проверки/отладки уже не нужны */ @@ -975,7 +974,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si if (unlikely(env->flags & MDBX_RDONLY)) return LOG_IFERR(MDBX_EACCESS); - if (!txn0_owned) { + if (!txn_owned) { int err = lck_txn_lock(env, false); if (unlikely(err != MDBX_SUCCESS)) return LOG_IFERR(err); @@ -989,8 +988,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si /* get untouched params from current TXN or DB */ if (pagesize <= 0 || pagesize >= INT_MAX) pagesize = env->ps; - const geo_t *const geo = - inside_txn ? &env->txn->geo : &meta_recent(env, &env->basal_txn->tw.troika).ptr_c->geometry; + const geo_t *const geo = env->txn ? &env->txn->geo : &meta_recent(env, &env->basal_txn->tw.troika).ptr_c->geometry; if (size_lower < 0) size_lower = pgno2bytes(env, geo->lower); if (size_now < 0) @@ -1015,7 +1013,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si size_now = usedbytes; } else { /* env NOT yet mapped */ - if (unlikely(inside_txn)) + if (unlikely(env->txn)) return LOG_IFERR(MDBX_PANIC); /* is requested some auto-value for pagesize ? */ @@ -1204,8 +1202,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si ENSURE(env, pagesize == (intptr_t)env->ps); meta_t meta; memset(&meta, 0, sizeof(meta)); - if (!inside_txn) { - eASSERT(env, should_unlock); + if (!env->txn) { const meta_ptr_t head = meta_recent(env, &env->basal_txn->tw.troika); uint64_t timestamp = 0; @@ -1295,7 +1292,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si if (unlikely(rc != MDBX_SUCCESS)) goto bailout; } - if (inside_txn) { + if (env->txn) { env->txn->geo = new_geo; env->txn->flags |= MDBX_TXN_DIRTY; } else { @@ -1420,17 +1417,17 @@ __cold int mdbx_env_stat_ex(const MDBX_env *env, const MDBX_txn *txn, MDBX_stat if (unlikely(err != MDBX_SUCCESS)) return LOG_IFERR(err); - if (env->txn && env_txn0_owned(env)) + MDBX_txn *txn_owned = env_owned_wrtxn(env); + if (txn_owned) /* inside write-txn */ - return LOG_IFERR(stat_acc(env->txn, dest, bytes)); + return LOG_IFERR(stat_acc(txn_owned, dest, bytes)); - MDBX_txn *tmp_txn; - err = mdbx_txn_begin((MDBX_env *)env, nullptr, MDBX_TXN_RDONLY, &tmp_txn); + err = mdbx_txn_begin((MDBX_env *)env, nullptr, MDBX_TXN_RDONLY, &txn_owned); if (unlikely(err != MDBX_SUCCESS)) return LOG_IFERR(err); - const int rc = stat_acc(tmp_txn, dest, bytes); - err = mdbx_txn_abort(tmp_txn); + const int rc = stat_acc(txn_owned, dest, bytes); + err = mdbx_txn_abort(txn_owned); if (unlikely(err != MDBX_SUCCESS)) return LOG_IFERR(err); return LOG_IFERR(rc); diff --git a/src/api-opts.c b/src/api-opts.c index 2465864a..4f13d875 100644 --- a/src/api-opts.c +++ b/src/api-opts.c @@ -180,7 +180,7 @@ __cold int mdbx_env_set_option(MDBX_env *env, const MDBX_option_t option, uint64 if (unlikely(err != MDBX_SUCCESS)) return LOG_IFERR(err); - const bool lock_needed = ((env->flags & ENV_ACTIVE) && env->basal_txn && !env_txn0_owned(env)); + const bool lock_needed = ((env->flags & ENV_ACTIVE) && env->basal_txn && !env_owned_wrtxn(env)); bool should_unlock = false; switch (option) { case MDBX_opt_sync_bytes: diff --git a/src/dxb.c b/src/dxb.c index 22379d33..2b3cc03a 100644 --- a/src/dxb.c +++ b/src/dxb.c @@ -368,7 +368,7 @@ void dxb_sanitize_tail(MDBX_env *env, MDBX_txn *txn) { if (env->pid != osal_getpid()) { /* resurrect after fork */ return; - } else if (env->txn && env_txn0_owned(env)) { + } else if (env_owned_wrtxn(env)) { /* inside write-txn */ last = meta_recent(env, &env->basal_txn->tw.troika).ptr_v->geometry.first_unallocated; } else if (env->flags & MDBX_RDONLY) { diff --git a/src/env.c b/src/env.c index 525ed8ec..e9b33646 100644 --- a/src/env.c +++ b/src/env.c @@ -3,9 +3,14 @@ #include "internals.h" -bool env_txn0_owned(const MDBX_env *env) { - return (env->flags & MDBX_NOSTICKYTHREADS) ? (env->basal_txn->owner != 0) - : (env->basal_txn->owner == osal_thread_self()); +MDBX_txn *env_owned_wrtxn(const MDBX_env *env) { + if (likely(env->basal_txn)) { + const bool is_owned = (env->flags & MDBX_NOSTICKYTHREADS) ? (env->basal_txn->owner != 0) + : (env->basal_txn->owner == osal_thread_self()); + if (is_owned) + return env->txn ? env->txn : env->basal_txn; + } + return nullptr; } int env_page_auxbuffer(MDBX_env *env) { @@ -60,7 +65,7 @@ __cold int env_sync(MDBX_env *env, bool force, bool nonblock) { if (unlikely(env->flags & MDBX_RDONLY)) return MDBX_EACCESS; - const bool txn0_owned = env_txn0_owned(env); + MDBX_txn *const txn_owned = env_owned_wrtxn(env); bool should_unlock = false; int rc = MDBX_RESULT_TRUE /* means "nothing to sync" */; @@ -71,7 +76,7 @@ retry:; goto bailout; } - const troika_t troika = (txn0_owned | should_unlock) ? env->basal_txn->tw.troika : meta_tap(env); + const troika_t troika = (txn_owned || should_unlock) ? env->basal_txn->tw.troika : meta_tap(env); const meta_ptr_t head = meta_recent(env, &troika); const uint64_t unsynced_pages = atomic_load64(&env->lck->unsynced_pages, mo_Relaxed); if (unsynced_pages == 0) { @@ -104,7 +109,7 @@ retry:; osal_monotime() - eoos_timestamp >= autosync_period)) flags &= MDBX_WRITEMAP /* clear flags for full steady sync */; - if (!txn0_owned) { + if (!txn_owned) { if (!should_unlock) { #if MDBX_ENABLE_PGOP_STAT unsigned wops = 0; @@ -163,8 +168,8 @@ retry:; flags |= txn_shrink_allowed; } - eASSERT(env, txn0_owned || should_unlock); - eASSERT(env, !txn0_owned || (flags & txn_shrink_allowed) == 0); + eASSERT(env, txn_owned || should_unlock); + eASSERT(env, !txn_owned || (flags & txn_shrink_allowed) == 0); if (!head.is_steady && unlikely(env->stuck_meta >= 0) && troika.recent != (uint8_t)env->stuck_meta) { NOTICE("skip %s since wagering meta-page (%u) is mispatch the recent " diff --git a/src/proto.h b/src/proto.h index 842cbf62..f0a6657f 100644 --- a/src/proto.h +++ b/src/proto.h @@ -76,7 +76,7 @@ MDBX_INTERNAL int env_open(MDBX_env *env, mdbx_mode_t mode); MDBX_INTERNAL int env_info(const MDBX_env *env, const MDBX_txn *txn, MDBX_envinfo *out, size_t bytes, troika_t *troika); MDBX_INTERNAL int env_sync(MDBX_env *env, bool force, bool nonblock); MDBX_INTERNAL int env_close(MDBX_env *env, bool resurrect_after_fork); -MDBX_INTERNAL bool env_txn0_owned(const MDBX_env *env); +MDBX_INTERNAL MDBX_txn *env_owned_wrtxn(const MDBX_env *env); MDBX_INTERNAL int __must_check_result env_page_auxbuffer(MDBX_env *env); MDBX_INTERNAL unsigned env_setup_pagesize(MDBX_env *env, const size_t pagesize);