mirror of
https://github.com/isar/libmdbx.git
synced 2025-04-26 06:32:25 +08:00
mdbx: fix growth memory-mapping on Windows.
This resolves https://github.com/leo-yuriev/libmdbx/issues/22 Change-Id: I25c2e65d9f68da8012ee097d3ad579cd548f2e09
This commit is contained in:
parent
91a9d4d916
commit
897d4dbf87
83
src/osal.c
83
src/osal.c
@ -771,11 +771,18 @@ int mdbx_msync(mdbx_mmap_t *map, size_t offset, size_t length, int async) {
|
|||||||
int mdbx_mmap(int flags, mdbx_mmap_t *map, size_t must, size_t limit) {
|
int mdbx_mmap(int flags, mdbx_mmap_t *map, size_t must, size_t limit) {
|
||||||
assert(must <= limit);
|
assert(must <= limit);
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
NTSTATUS rc;
|
||||||
|
|
||||||
map->length = 0;
|
map->length = 0;
|
||||||
map->current = 0;
|
map->current = 0;
|
||||||
map->section = NULL;
|
map->section = NULL;
|
||||||
map->address = nullptr;
|
map->address = nullptr;
|
||||||
|
|
||||||
|
uint64_t filesize;
|
||||||
|
rc = mdbx_filesize(map->fd, &filesize);
|
||||||
|
if (rc != MDBX_SUCCESS)
|
||||||
|
return rc;
|
||||||
|
|
||||||
if (GetFileType(map->fd) != FILE_TYPE_DISK)
|
if (GetFileType(map->fd) != FILE_TYPE_DISK)
|
||||||
return ERROR_FILE_OFFLINE;
|
return ERROR_FILE_OFFLINE;
|
||||||
|
|
||||||
@ -789,7 +796,6 @@ int mdbx_mmap(int flags, mdbx_mmap_t *map, size_t must, size_t limit) {
|
|||||||
return ERROR_FILE_OFFLINE;
|
return ERROR_FILE_OFFLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS rc;
|
|
||||||
#if defined(_WIN64) && defined(WOF_CURRENT_VERSION)
|
#if defined(_WIN64) && defined(WOF_CURRENT_VERSION)
|
||||||
struct {
|
struct {
|
||||||
WOF_EXTERNAL_INFO wof_info;
|
WOF_EXTERNAL_INFO wof_info;
|
||||||
@ -855,13 +861,20 @@ int mdbx_mmap(int flags, mdbx_mmap_t *map, size_t must, size_t limit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filesize > must) {
|
||||||
|
rc = mdbx_ftruncate(map->fd, must);
|
||||||
|
(void)rc /* ignore error, because Windows unable shrink mapped file */;
|
||||||
|
}
|
||||||
|
|
||||||
|
LARGE_INTEGER SectionSize;
|
||||||
|
SectionSize.QuadPart = must;
|
||||||
rc = NtCreateSection(
|
rc = NtCreateSection(
|
||||||
&map->section,
|
&map->section,
|
||||||
/* DesiredAccess */ (flags & MDBX_WRITEMAP)
|
/* DesiredAccess */ (flags & MDBX_WRITEMAP)
|
||||||
? SECTION_QUERY | SECTION_MAP_READ | SECTION_EXTEND_SIZE |
|
? SECTION_QUERY | SECTION_MAP_READ | SECTION_EXTEND_SIZE |
|
||||||
SECTION_MAP_WRITE
|
SECTION_MAP_WRITE
|
||||||
: SECTION_QUERY | SECTION_MAP_READ | SECTION_EXTEND_SIZE,
|
: SECTION_QUERY | SECTION_MAP_READ | SECTION_EXTEND_SIZE,
|
||||||
/* ObjectAttributes */ NULL, /* MaximumSize */ NULL,
|
/* ObjectAttributes */ NULL, /* MaximumSize (InitialSize) */ &SectionSize,
|
||||||
/* SectionPageProtection */ (flags & MDBX_RDONLY) ? PAGE_READONLY
|
/* SectionPageProtection */ (flags & MDBX_RDONLY) ? PAGE_READONLY
|
||||||
: PAGE_READWRITE,
|
: PAGE_READWRITE,
|
||||||
/* AllocationAttributes */ SEC_RESERVE, map->fd);
|
/* AllocationAttributes */ SEC_RESERVE, map->fd);
|
||||||
@ -869,12 +882,11 @@ int mdbx_mmap(int flags, mdbx_mmap_t *map, size_t must, size_t limit) {
|
|||||||
if (!NT_SUCCESS(rc))
|
if (!NT_SUCCESS(rc))
|
||||||
return ntstatus2errcode(rc);
|
return ntstatus2errcode(rc);
|
||||||
|
|
||||||
map->address = nullptr;
|
SIZE_T ViewSize = limit;
|
||||||
SIZE_T ViewSize = (flags & MDBX_RDONLY) ? must : limit;
|
|
||||||
rc = NtMapViewOfSection(
|
rc = NtMapViewOfSection(
|
||||||
map->section, GetCurrentProcess(), &map->address,
|
map->section, GetCurrentProcess(), &map->address,
|
||||||
/* ZeroBits */ 0,
|
/* ZeroBits */ 0,
|
||||||
/* CommitSize */ must,
|
/* CommitSize */ 0,
|
||||||
/* SectionOffset */ NULL, &ViewSize,
|
/* SectionOffset */ NULL, &ViewSize,
|
||||||
/* InheritDisposition */ ViewUnmap,
|
/* InheritDisposition */ ViewUnmap,
|
||||||
/* AllocationType */ (flags & MDBX_RDONLY) ? 0 : MEM_RESERVE,
|
/* AllocationType */ (flags & MDBX_RDONLY) ? 0 : MEM_RESERVE,
|
||||||
@ -889,17 +901,7 @@ int mdbx_mmap(int flags, mdbx_mmap_t *map, size_t must, size_t limit) {
|
|||||||
}
|
}
|
||||||
assert(map->address != MAP_FAILED);
|
assert(map->address != MAP_FAILED);
|
||||||
|
|
||||||
uint64_t filesize;
|
map->current = (size_t)SectionSize.QuadPart;
|
||||||
rc = mdbx_filesize(map->fd, &filesize);
|
|
||||||
if (rc != MDBX_SUCCESS) {
|
|
||||||
NtClose(map->section);
|
|
||||||
NtUnmapViewOfSection(GetCurrentProcess(), map->address);
|
|
||||||
map->section = 0;
|
|
||||||
map->address = nullptr;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
map->current = (must < filesize) ? must : (size_t)filesize;
|
|
||||||
map->length = ViewSize;
|
map->length = ViewSize;
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
#else
|
#else
|
||||||
@ -939,47 +941,24 @@ int mdbx_munmap(mdbx_mmap_t *map) {
|
|||||||
int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t atleast, size_t limit) {
|
int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t atleast, size_t limit) {
|
||||||
assert(atleast <= limit);
|
assert(atleast <= limit);
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
if (limit < map->length) {
|
if (limit != map->length) {
|
||||||
/* Windows is unable shrinking a mapped section */
|
int rc = mdbx_munmap(map);
|
||||||
return ERROR_USER_MAPPED_FILE;
|
if (rc == MDBX_SUCCESS)
|
||||||
}
|
rc = mdbx_mmap(flags, map, atleast, limit);
|
||||||
if (limit > map->length) {
|
return rc;
|
||||||
/* extend */
|
|
||||||
LARGE_INTEGER new_size;
|
|
||||||
new_size.QuadPart = limit;
|
|
||||||
NTSTATUS rc = NtExtendSection(map->section, &new_size);
|
|
||||||
if (!NT_SUCCESS(rc))
|
|
||||||
return ntstatus2errcode(rc);
|
|
||||||
map->length = limit;
|
|
||||||
}
|
|
||||||
if (atleast < map->current) {
|
|
||||||
/* Windows is unable shrinking a mapped file */
|
|
||||||
uint8_t *ptr = (uint8_t *)map->address + atleast;
|
|
||||||
if (!VirtualFree(ptr, map->current - atleast, MEM_DECOMMIT))
|
|
||||||
return MDBX_RESULT_TRUE;
|
|
||||||
|
|
||||||
map->current = atleast;
|
|
||||||
int rc = mdbx_ftruncate(map->fd, atleast);
|
|
||||||
return (rc != MDBX_SUCCESS) ? MDBX_RESULT_TRUE : rc;
|
|
||||||
}
|
}
|
||||||
if (atleast > map->current) {
|
if (atleast > map->current) {
|
||||||
/* growth */
|
/* growth */
|
||||||
uint8_t *ptr = (uint8_t *)map->address + map->current;
|
LARGE_INTEGER new_size;
|
||||||
if (ptr !=
|
new_size.QuadPart = atleast;
|
||||||
VirtualAlloc(ptr, atleast - map->current, MEM_COMMIT | MEM_RESERVE,
|
NTSTATUS rc = NtExtendSection(map->section, &new_size);
|
||||||
(flags & MDBX_WRITEMAP) ? PAGE_READWRITE : PAGE_READONLY))
|
|
||||||
return GetLastError();
|
|
||||||
map->current = atleast;
|
map->current = atleast;
|
||||||
|
if (!NT_SUCCESS(rc))
|
||||||
|
return ntstatus2errcode(rc);
|
||||||
}
|
}
|
||||||
|
if (atleast < map->current) {
|
||||||
uint64_t filesize;
|
/* Windows unable shrinking a mapped file */
|
||||||
int rc = mdbx_filesize(map->fd, &filesize);
|
return MDBX_RESULT_TRUE;
|
||||||
if (rc != MDBX_SUCCESS)
|
|
||||||
return rc;
|
|
||||||
if (filesize < atleast) {
|
|
||||||
rc = mdbx_ftruncate(map->fd, atleast);
|
|
||||||
if (rc != MDBX_SUCCESS)
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
#else
|
#else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user