diff --git a/mdbx.h b/mdbx.h index c4712c73..09143488 100644 --- a/mdbx.h +++ b/mdbx.h @@ -1684,6 +1684,7 @@ LIBMDBX_API MDBX_oom_func *mdbx_env_get_oomfunc(MDBX_env *env); #define MDBX_DBG_AUDIT 16 #define MDBX_DBG_JITTER 32 #define MDBX_DBG_DUMP 64 +#define MDBX_DBG_LEGACY_MULTIOPEN 128 typedef void MDBX_debug_func(int type, const char *function, int line, const char *msg, va_list args); diff --git a/src/lck-linux.c b/src/lck-linux.c index e9e48b04..151ba325 100644 --- a/src/lck-linux.c +++ b/src/lck-linux.c @@ -37,12 +37,10 @@ #endif #endif /* MDBX_USE_ROBUST */ -uint32_t linux_kernel_version; -static int op_setlk = F_SETLK, op_setlkw = F_SETLKW, op_getlk = F_GETLK; - /*----------------------------------------------------------------------------*/ /* global constructor/destructor */ +uint32_t mdbx_linux_kernel_version; static __cold __attribute__((constructor)) void mdbx_global_constructor(void) { struct utsname buffer; if (uname(&buffer) == 0) { @@ -54,7 +52,7 @@ static __cold __attribute__((constructor)) void mdbx_global_constructor(void) { if (number > 0) { if (number > 255) number = 255; - linux_kernel_version += number << (24 - i * 8); + mdbx_linux_kernel_version += number << (24 - i * 8); } ++i; } else { @@ -63,16 +61,6 @@ static __cold __attribute__((constructor)) void mdbx_global_constructor(void) { } } -#if defined(F_OFD_SETLK) && defined(F_OFD_SETLKW) && defined(F_OFD_GETLK) - if (linux_kernel_version > - 0x030f0000 /* OFD locks are available since 3.15, but engages here only - for 3.16 and larer kernels (LTS) for reliability reasons */) { - op_setlk = F_OFD_SETLK; - op_setlkw = F_OFD_SETLKW; - op_getlk = F_OFD_GETLK; - } -#endif /* OFD locks */ - mdbx_rthc_global_init(); } @@ -118,6 +106,25 @@ static __cold __attribute__((destructor)) void mdbx_global_destructor(void) { * и атомарным режимами блокировок. */ +static int op_setlk, op_setlkw, op_getlk; +static void __cold choice_fcntl() { + assert(!op_setlk && !op_setlkw && !op_getlk); +#if defined(F_OFD_SETLK) && defined(F_OFD_SETLKW) && defined(F_OFD_GETLK) + if (mdbx_linux_kernel_version > + 0x030f0000 /* OFD locks are available since 3.15, but engages here + only for 3.16 and larer kernels (LTS) for reliability reasons */ + && (mdbx_runtime_flags & MDBX_DBG_LEGACY_MULTIOPEN) == 0) { + op_setlk = F_OFD_SETLK; + op_setlkw = F_OFD_SETLKW; + op_getlk = F_OFD_GETLK; + return; + } +#endif /* OFD locks */ + op_setlk = F_SETLK; + op_setlkw = F_SETLKW; + op_getlk = F_GETLK; +} + #ifndef OFF_T_MAX #define OFF_T_MAX \ ((sizeof(off_t) > 4 ? INT64_MAX : INT32_MAX) & ~(size_t)0xffff) @@ -341,6 +348,8 @@ static int __cold internal_seize_lck(int lfd) { int __cold mdbx_lck_seize(MDBX_env *env) { assert(env->me_fd != INVALID_HANDLE_VALUE); + if (unlikely(op_setlk == 0)) + choice_fcntl(); if (env->me_lfd == INVALID_HANDLE_VALUE) { /* LY: without-lck mode (e.g. exclusive or on read-only filesystem) */ diff --git a/src/mdbx.c b/src/mdbx.c index 61098380..d44b47b5 100644 --- a/src/mdbx.c +++ b/src/mdbx.c @@ -12917,36 +12917,51 @@ int __cold mdbx_reader_check0(MDBX_env *env, int rdt_locked, int *dead) { } int __cold mdbx_setup_debug(int flags, MDBX_debug_func *logger) { - unsigned ret = mdbx_runtime_flags; - mdbx_runtime_flags = flags; - + const int rc = mdbx_runtime_flags; + if (flags != -1) { +#if MDBX_DEBUG + flags &= MDBX_DBG_DUMP | MDBX_DBG_LEGACY_MULTIOPEN; +#else + flags &= MDBX_DBG_ASSERT | MDBX_DBG_PRINT | MDBX_DBG_TRACE | + MDBX_DBG_EXTRA | MDBX_DBG_AUDIT | MDBX_DBG_JITTER | MDBX_DBG_DUMP | + MDBX_DBG_LEGACY_MULTIOPEN; +#endif #if defined(__linux__) || defined(__gnu_linux__) - if (flags & MDBX_DBG_DUMP) { - int core_filter_fd = open("/proc/self/coredump_filter", O_TRUNC | O_RDWR); - if (core_filter_fd >= 0) { - char buf[32]; - const unsigned r = pread(core_filter_fd, buf, sizeof(buf), 0); - if (r > 0 && r < sizeof(buf)) { - buf[r] = 0; - unsigned long mask = strtoul(buf, NULL, 16); - if (mask != ULONG_MAX) { - mask |= 1 << 3 /* Dump file-backed shared mappings */; - mask |= 1 << 6 /* Dump shared huge pages */; - mask |= 1 << 8 /* Dump shared DAX pages */; - unsigned w = snprintf(buf, sizeof(buf), "0x%lx\n", mask); - if (w > 0 && w < sizeof(buf)) { - w = pwrite(core_filter_fd, buf, w, 0); - (void)w; + if ((mdbx_runtime_flags ^ flags) & MDBX_DBG_DUMP) { + /* http://man7.org/linux/man-pages/man5/core.5.html */ + const unsigned long dump_bits = + 1 << 3 /* Dump file-backed shared mappings */ + | 1 << 6 /* Dump shared huge pages */ + | 1 << 8 /* Dump shared DAX pages */; + const int core_filter_fd = + open("/proc/self/coredump_filter", O_TRUNC | O_RDWR); + if (core_filter_fd != -1) { + char buf[32]; + intptr_t bytes = pread(core_filter_fd, buf, sizeof(buf), 0); + if (bytes > 0 && (size_t)bytes < sizeof(buf)) { + buf[bytes] = 0; + const unsigned long present_mask = strtoul(buf, NULL, 16); + const unsigned long wanna_mask = (flags & MDBX_DBG_DUMP) + ? present_mask | dump_bits + : present_mask & ~dump_bits; + if (wanna_mask != present_mask) { + bytes = snprintf(buf, sizeof(buf), "0x%lx\n", wanna_mask); + if (bytes > 0 && (size_t)bytes < sizeof(buf)) { + bytes = pwrite(core_filter_fd, buf, bytes, 0); + (void)bytes; + } } } + close(core_filter_fd); } - close(core_filter_fd); } - } #endif /* Linux */ + mdbx_runtime_flags = flags; + } - mdbx_debug_logger = logger; - return ret; + if (-1 != (intptr_t)logger) + mdbx_debug_logger = logger; + return rc; } static txnid_t __cold mdbx_oomkick(MDBX_env *env, const txnid_t laggard) { diff --git a/src/osal.c b/src/osal.c index e0ae3f47..8fb23c59 100644 --- a/src/osal.c +++ b/src/osal.c @@ -674,7 +674,7 @@ int mdbx_filesync(mdbx_filehandle_t fd, enum mdbx_syncmode_bits mode_bits) { return likely(fcntl(fd, F_FULLFSYNC) != -1) ? MDBX_SUCCESS : errno; #endif /* MacOS */ #if defined(__linux__) || defined(__gnu_linux__) - if (mode_bits == MDBX_SYNC_SIZE && linux_kernel_version >= 0x03060000) + if (mode_bits == MDBX_SYNC_SIZE && mdbx_linux_kernel_version >= 0x03060000) return MDBX_SUCCESS; #endif /* Linux */ int rc; @@ -789,7 +789,7 @@ int mdbx_msync(mdbx_mmap_t *map, size_t offset, size_t length, int async) { return GetLastError(); #else #ifdef __linux__ - if (async && linux_kernel_version > 0x02061300) + if (async && mdbx_linux_kernel_version > 0x02061300) /* Since Linux 2.6.19, MS_ASYNC is in fact a no-op, since the kernel properly tracks dirty pages and flushes them to storage as necessary. */ diff --git a/src/osal.h b/src/osal.h index 90189762..45d4cf39 100644 --- a/src/osal.h +++ b/src/osal.h @@ -475,7 +475,7 @@ int mdbx_vasprintf(char **strp, const char *fmt, va_list ap); #define MAX_WRITE UINT32_C(0x3fff0000) #if defined(__linux__) || defined(__gnu_linux__) -extern uint32_t linux_kernel_version; +extern uint32_t mdbx_linux_kernel_version; #endif /* Linux */ /* Get the size of a memory page for the system.