From 17c6555a7fef4eb8711e826bf3401b8b9b6e93cf Mon Sep 17 00:00:00 2001 From: Leo Yuriev Date: Mon, 21 Nov 2016 20:50:39 +0300 Subject: [PATCH] mdbx: add 'canary' support for libfpta. Change-Id: I62c68f149adf38d65aa9371a1fb3adac405d23ed --- mdb.c | 22 +++++++++++++++++++++- mdbx.c | 32 ++++++++++++++++++++++++++++++++ mdbx.h | 8 ++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/mdb.c b/mdb.c index edf088ec..45fcc5e6 100644 --- a/mdb.c +++ b/mdb.c @@ -778,6 +778,10 @@ typedef struct MDB_meta { volatile uint64_t mm_datasync_sign; #define META_IS_WEAK(meta) ((meta)->mm_datasync_sign == MDB_DATASIGN_WEAK) #define META_IS_STEADY(meta) ((meta)->mm_datasync_sign > MDB_DATASIGN_WEAK) + +#if MDBX_MODE_ENABLED + volatile mdbx_canary mm_canary; +#endif } MDB_meta; /** Buffer for a stack-allocated meta page. @@ -809,7 +813,7 @@ typedef struct MDB_dbx { * Every operation requires a transaction handle. */ struct MDB_txn { -#define MDBX_MT_SIGNATURE 0x706C553B +#define MDBX_MT_SIGNATURE 0x93D53A31 unsigned mt_signature; MDB_txn *mt_parent; /**< parent of a nested txn */ /** Nested txn under this txn, set together with flag #MDB_TXN_HAS_CHILD */ @@ -895,6 +899,10 @@ struct MDB_txn { * dirty_list into mt_parent after freeing hidden mt_parent pages. */ unsigned mt_dirty_room; + +#if MDBX_MODE_ENABLED + mdbx_canary mt_canary; +#endif }; /** Enough space for 2^32 nodes with minimum of 2 keys per node. I.e., plenty. @@ -2842,6 +2850,9 @@ mdb_txn_renew0(MDB_txn *txn, unsigned flags) txn->mt_next_pgno = meta->mm_last_pg+1; /* Copy the DB info and flags */ memcpy(txn->mt_dbs, meta->mm_dbs, CORE_DBS * sizeof(MDB_db)); +#if MDBX_MODE_ENABLED + txn->mt_canary = meta->mm_canary; +#endif break; } } @@ -2858,6 +2869,9 @@ mdb_txn_renew0(MDB_txn *txn, unsigned flags) pthread_mutex_lock(&tsan_mutex); #endif MDB_meta *meta = mdb_meta_head_w(env); +#if MDBX_MODE_ENABLED + txn->mt_canary = meta->mm_canary; +#endif txn->mt_txnid = meta->mm_txnid + 1; txn->mt_flags = flags; #ifdef __SANITIZE_THREAD__ @@ -3919,6 +3933,9 @@ mdb_txn_commit(MDB_txn *txn) meta.mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI]; meta.mm_last_pg = txn->mt_next_pgno - 1; meta.mm_txnid = txn->mt_txnid; +#if MDBX_MODE_ENABLED + meta.mm_canary = txn->mt_canary; +#endif rc = mdb_env_sync0(env, env->me_flags | txn->mt_flags, &meta); } @@ -4155,6 +4172,9 @@ mdb_env_sync0(MDB_env *env, unsigned flags, MDB_meta *pending) target->mm_dbs[FREE_DBI] = pending->mm_dbs[FREE_DBI]; target->mm_dbs[MAIN_DBI] = pending->mm_dbs[MAIN_DBI]; target->mm_last_pg = pending->mm_last_pg; +#if MDBX_MODE_ENABLED + target->mm_canary = pending->mm_canary; +#endif /* LY: 'commit' the meta */ target->mm_txnid = pending->mm_txnid; target->mm_datasync_sign = pending->mm_datasync_sign; diff --git a/mdbx.c b/mdbx.c index fb4aac85..cf5187fe 100644 --- a/mdbx.c +++ b/mdbx.c @@ -320,3 +320,35 @@ mdbx_env_pgwalk(MDB_txn *txn, MDBX_pgvisitor_func* visitor, void* user) rc = visitor(P_INVALID, 0, user, NULL, NULL, 0, 0, 0, 0); return rc; } + +int mdbx_canary_put(MDB_txn *txn, const mdbx_canary* canary) +{ + if (unlikely(!txn)) + return EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDB_VERSION_MISMATCH; + + if (unlikely(F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))) + return EACCES; + + if (likely(canary)) { + txn->mt_canary.x = canary->x; + txn->mt_canary.y = canary->y; + txn->mt_canary.z = canary->z; + } + txn->mt_canary.v = txn->mt_txnid; + + return MDB_SUCCESS; +} + +size_t mdbx_canary_get(MDB_txn *txn, mdbx_canary* canary) +{ + if(unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE)) + return 0; + + if (likely(canary)) + *canary = txn->mt_canary; + + return txn->mt_txnid; +} diff --git a/mdbx.h b/mdbx.h index bcbd4f47..d494ef36 100644 --- a/mdbx.h +++ b/mdbx.h @@ -211,6 +211,14 @@ typedef int MDBX_pgvisitor_func(size_t pgno, unsigned pgnumber, void* ctx, const char* dbi, const char *type, int nentries, int payload_bytes, int header_bytes, int unused_bytes); int mdbx_env_pgwalk(MDB_txn *txn, MDBX_pgvisitor_func* visitor, void* ctx); + +typedef struct mdbx_canary { + size_t x, y, z, v; +} mdbx_canary; + +int mdbx_canary_put(MDB_txn *txn, const mdbx_canary* canary); +size_t mdbx_canary_get(MDB_txn *txn, mdbx_canary* canary); + /** @} */ #ifdef __cplusplus