mirror of
				https://github.com/isar/libmdbx.git
				synced 2025-11-04 05:08:57 +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:
		
							
								
								
									
										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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user