]> git.sur5r.net Git - openldap/commitdiff
ITS#8582 Fill in MDB_LOCK_FORMAT
authorHallvard Furuseth <hallvard@openldap.org>
Sun, 12 Mar 2017 19:08:53 +0000 (20:08 +0100)
committerHallvard Furuseth <hallvard@openldap.org>
Sun, 19 Mar 2017 12:24:08 +0000 (13:24 +0100)
Attempt to stop liblmdb variants compiled with conflicting options
from using the lockfile at the same time and thus breaking it.

libraries/liblmdb/mdb.c

index 59e3d938b1668621f9f3c98dac41c7f6a06279c8..4a364f7fdb437c095e41057920a3c635d664c06c 100644 (file)
@@ -480,12 +480,6 @@ typedef pthread_mutex_t *mdb_mutexref_t;
 #define MUTEXNAME_PREFIX               "/MDB"
 #endif
 
-#ifdef MDB_USE_SYSV_SEM
-#define SYSV_SEM_FLAG  1               /**< SysV sems in lockfile format */
-#else
-#define SYSV_SEM_FLAG  0
-#endif
-
 /** @} */
 
 #ifdef MDB_ROBUST_SUPPORTED
@@ -628,6 +622,10 @@ static txnid_t mdb_debug_start;
 #define MDB_DATA_VERSION        ((MDB_DEVEL) ? 999 : 1)
        /**     The version number for a database's lockfile format. */
 #define MDB_LOCK_VERSION        ((MDB_DEVEL) ? 999 : 2)
+       /** Number of bits representing #MDB_LOCK_VERSION in #MDB_LOCK_FORMAT.
+        *      The remaining bits must leave room for #MDB_lock_desc.
+        */
+#define MDB_LOCK_VERSION_BITS 12
 
        /**     @brief The max size of a key we can write, or 0 for computed max.
         *
@@ -693,6 +691,19 @@ static txnid_t mdb_debug_start;
        /** Round \b n up to an even number. */
 #define EVEN(n)                (((n) + 1U) & -2) /* sign-extending -2 to match n+1U */
 
+       /** Least significant 1-bit of \b n.  n must be of an unsigned type. */
+#define LOW_BIT(n)             ((n) & (-(n)))
+
+       /** (log2(\b p2) % \b n), for p2 = power of 2 and 0 < n < 8. */
+#define LOG2_MOD(p2, n)        (7 - 86 / ((p2) % ((1U<<(n))-1) + 11))
+       /* Explanation: Let p2 = 2**(n*y + x), x<n and M = (1U<<n)-1. Now p2 =
+        * (M+1)**y * 2**x = 2**x (mod M). Finally "/" "happens" to return 7-x.
+        */
+
+       /** Should be alignment of \b type. Ensure it is a power of 2. */
+#define ALIGNOF2(type) \
+       LOW_BIT(offsetof(struct { char ch_; type align_; }, align_))
+
        /**     Used for offsets within a single page.
         *      Since memory pages are typically 4 or 8KB in size, 12-13 bits,
         *      this is plenty.
@@ -849,7 +860,6 @@ typedef struct MDB_txninfo {
 #define mti_magic      mt1.mtb.mtb_magic
 #define mti_format     mt1.mtb.mtb_format
 #define mti_rmutex     mt1.mtb.mtb_rmutex
-#define mti_rmname     mt1.mtb.mtb_rmname
 #define mti_txnid      mt1.mtb.mtb_txnid
 #define mti_numreaders mt1.mtb.mtb_numreaders
 #define mti_mutexid    mt1.mtb.mtb_mutexid
@@ -876,11 +886,54 @@ typedef struct MDB_txninfo {
 
        /** Lockfile format signature: version, features and field layout */
 #define MDB_LOCK_FORMAT \
-       ((uint32_t) \
-        ((MDB_LOCK_VERSION) \
-         /* Flags which describe functionality */ \
-         + (SYSV_SEM_FLAG << 18) \
-         + (((MDB_PIDLOCK) != 0) << 16)))
+       ((uint32_t)         \
+        (((MDB_LOCK_VERSION) % (1U << MDB_LOCK_VERSION_BITS)) \
+         + MDB_lock_desc     * (1U << MDB_LOCK_VERSION_BITS)))
+
+       /** Lock type and layout. Values 0-119. _WIN32 implies #MDB_PIDLOCK.
+        *      Some low values are reserved for future tweaks.
+        */
+#ifdef _WIN32
+# define MDB_LOCK_TYPE (0 + ALIGNOF2(mdb_hash_t)/8 % 2)
+#elif defined MDB_USE_POSIX_SEM
+# define MDB_LOCK_TYPE (4 + ALIGNOF2(mdb_hash_t)/8 % 2)
+#elif defined MDB_USE_SYSV_SEM
+# define MDB_LOCK_TYPE (8)
+#elif defined MDB_USE_POSIX_MUTEX
+/* We do not know the inside of a POSIX mutex and how to check if mutexes
+ * used by two executables are compatible. Just check alignment and size.
+ */
+# define MDB_LOCK_TYPE (10 + \
+               LOG2_MOD(ALIGNOF2(pthread_mutex_t), 5) + \
+               sizeof(pthread_mutex_t) / 4U % 22 * 5)
+#endif
+
+enum {
+       /** Magic number for lockfile layout and features.
+        *
+        *  This *attempts* to stop liblmdb variants compiled with conflicting
+        *      options from using the lockfile at the same time and thus breaking
+        *      it.  It describes locking types, and sizes and sometimes alignment
+        *      of the various lockfile items.
+        *
+        *      The detected ranges are mostly guesswork, or based simply on how
+        *      big they could be without using more bits.  So we can tweak them
+        *      in good conscience when updating #MDB_LOCK_VERSION.
+        */
+       MDB_lock_desc =
+       /* Default CACHELINE=64 vs. other values (have seen mention of 32-256) */
+       (CACHELINE==64 ? 0 : 1 + LOG2_MOD(CACHELINE >> (CACHELINE>64), 5))
+       + 6  * (sizeof(MDB_PID_T)/4 % 3)    /* legacy(2) to word(4/8)? */
+       + 18 * (sizeof(pthread_t)/4 % 5)    /* can be struct{id, active data} */
+       + 90 * (sizeof(MDB_txbody) / CACHELINE % 3)
+       + 270 * (MDB_LOCK_TYPE % 120)
+       /* The above is < 270*120 < 2**15 */
+       + ((sizeof(txnid_t) == 8) << 15)    /* 32bit/64bit */
+       + ((sizeof(MDB_reader) > CACHELINE) << 16)
+       /* Not really needed - implied by MDB_LOCK_TYPE != (_WIN32 locking) */
+       + (((MDB_PIDLOCK) != 0)   << 17)
+       /* 18 bits total: Must be <= (32 - MDB_LOCK_VERSION_BITS). */
+};
 /** @} */
 
 /** Common header for all page types. The page type depends on #mp_flags.