From 6960c45e5947492cfa5a9a40a3b06ee65f5f2a70 Mon Sep 17 00:00:00 2001 From: Leonid Yuriev Date: Sat, 29 Jun 2019 18:34:56 +0300 Subject: [PATCH] mdbx: avoids EFAULT "Bad address" while copy-as-is if DB is swapped-out from RAM. Change-Id: I711efc1c54a04745bd561bc5e1db5e6f6d8b7115 --- src/mdbx.c | 28 +++++++++++++++++++--------- src/osal.c | 1 - 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/mdbx.c b/src/mdbx.c index 4799cf1a..8f193b6c 100644 --- a/src/mdbx.c +++ b/src/mdbx.c @@ -11253,7 +11253,7 @@ int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, } #ifndef MDBX_WBUF -#define MDBX_WBUF (1024 * 1024) +#define MDBX_WBUF ((size_t)1024 * 1024) #endif #define MDBX_EOF 0x10 /* mdbx_env_copyfd1() is done reading */ @@ -11632,12 +11632,13 @@ static int __cold mdbx_env_copy_asis(MDBX_env *env, MDBX_txn *read_txn, return rc; } + const size_t meta_bytes = pgno2bytes(env, NUM_METAS); /* Make a snapshot of meta-pages, * but writing ones after the data was flushed */ - memcpy(buffer, env->me_map, pgno2bytes(env, NUM_METAS)); + memcpy(buffer, env->me_map, meta_bytes); MDBX_meta *const headcopy = /* LY: get pointer to the spanshot copy */ (MDBX_meta *)(buffer + ((uint8_t *)mdbx_meta_head(env) - env->me_map)); - const uint64_t size = + const uint64_t whole_size = mdbx_roundup2(pgno2bytes(env, headcopy->mm_geo.now), env->me_os_psize); mdbx_txn_unlock(env); @@ -11645,12 +11646,19 @@ static int __cold mdbx_env_copy_asis(MDBX_env *env, MDBX_txn *read_txn, headcopy->mm_datasync_sign = mdbx_meta_sign(headcopy); /* Copy the data */ - rc = mdbx_pwrite(fd, env->me_map + pgno2bytes(env, NUM_METAS), - pgno2bytes(env, read_txn->mt_next_pgno - NUM_METAS), - pgno2bytes(env, NUM_METAS)); + const size_t data_bytes = pgno2bytes(env, read_txn->mt_next_pgno); + uint8_t *data_buffer = buffer + meta_bytes; + for (size_t offset = meta_bytes; + likely(rc == MDBX_SUCCESS) && offset < data_bytes;) { + const size_t chunk = + (MDBX_WBUF < data_bytes - offset) ? MDBX_WBUF : data_bytes - offset; + memcpy(data_buffer, env->me_map + offset, chunk); + rc = mdbx_pwrite(fd, data_buffer, chunk, offset); + offset += chunk; + } if (likely(rc == MDBX_SUCCESS)) - rc = mdbx_ftruncate(fd, size); + rc = mdbx_ftruncate(fd, whole_size); return rc; } @@ -11667,8 +11675,10 @@ int __cold mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd, if (unlikely(rc != MDBX_SUCCESS)) return rc; - const size_t buffer_size = pgno2bytes(env, NUM_METAS) + - ((flags & MDBX_CP_COMPACT) ? MDBX_WBUF * 2 : 0); + const size_t buffer_size = + pgno2bytes(env, NUM_METAS) + + ((flags & MDBX_CP_COMPACT) ? MDBX_WBUF * 2 : MDBX_WBUF); + uint8_t *buffer = NULL; rc = mdbx_memalign_alloc(env->me_os_psize, buffer_size, (void **)&buffer); if (unlikely(rc != MDBX_SUCCESS)) diff --git a/src/osal.c b/src/osal.c index 2ee74441..d3293d6f 100644 --- a/src/osal.c +++ b/src/osal.c @@ -544,7 +544,6 @@ int mdbx_pread(mdbx_filehandle_t fd, void *buf, size_t bytes, uint64_t offset) { if (bytes > MAX_WRITE) return MDBX_EINVAL; #if defined(_WIN32) || defined(_WIN64) - OVERLAPPED ov; ov.hEvent = 0; ov.Offset = (DWORD)offset;