mdbx: refine setup_debug(), add MDBX_DBG_LEGACY_MULTIOPEN.

Change-Id: I5d144f6fa27b8f5885fa0a0fbd11fe1d44bcc41c
This commit is contained in:
Leonid Yuriev 2019-08-23 21:38:33 +03:00
parent 33a4f31f92
commit 93f82f47bd
5 changed files with 65 additions and 40 deletions

1
mdbx.h
View File

@ -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);

View File

@ -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) */

View File

@ -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) {

View File

@ -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. */

View File

@ -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.