mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-04 18:14:12 +08:00
mdbx: rework/refine mdbx_mresize() for POSIX and MAP_FIXED_NOREPLACE (Linux 4.17).
Change-Id: I2e531b5e3e009b2a18ae1901fc7e2e6e4df667cd
This commit is contained in:
parent
5c89717ecd
commit
24c0749eb8
136
src/osal.c
136
src/osal.c
@ -1589,45 +1589,87 @@ retry_mapview:;
|
|||||||
map->current = size;
|
map->current = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (limit != map->limit) {
|
if (limit == map->limit)
|
||||||
|
return MDBX_SUCCESS;
|
||||||
|
|
||||||
|
if (limit < map->limit) {
|
||||||
|
/* unmap an excess at end of mapping. */
|
||||||
|
if (unlikely(munmap(map->dxb + limit, map->limit - limit)))
|
||||||
|
return errno;
|
||||||
|
map->limit = limit;
|
||||||
|
return MDBX_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(limit > map->limit);
|
||||||
|
uint8_t *ptr = MAP_FAILED;
|
||||||
|
|
||||||
#if defined(MREMAP_MAYMOVE)
|
#if defined(MREMAP_MAYMOVE)
|
||||||
void *ptr =
|
ptr = mremap(map->address, map->limit, limit, may_move ? MREMAP_MAYMOVE : 0);
|
||||||
mremap(map->address, map->limit, limit, may_move ? MREMAP_MAYMOVE : 0);
|
if (ptr == MAP_FAILED) {
|
||||||
if (ptr == MAP_FAILED) {
|
const int err = errno;
|
||||||
rc = errno;
|
switch (err) {
|
||||||
switch (rc) {
|
default:
|
||||||
|
return err;
|
||||||
|
case EAGAIN:
|
||||||
|
case ENOMEM:
|
||||||
|
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||||
|
case EFAULT /* MADV_DODUMP / MADV_DONTDUMP are mixed for mmap-range */:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* MREMAP_MAYMOVE */
|
||||||
|
|
||||||
|
const unsigned mmap_flags =
|
||||||
|
MAP_CONCEAL | MAP_SHARED | MAP_FILE |
|
||||||
|
(F_ISSET(flags, MDBX_UTTERLY_NOSYNC) ? MAP_NOSYNC : 0);
|
||||||
|
const unsigned mmap_prot =
|
||||||
|
(flags & MDBX_WRITEMAP) ? PROT_READ | PROT_WRITE : PROT_READ;
|
||||||
|
|
||||||
|
if (ptr == MAP_FAILED) {
|
||||||
|
/* Try to mmap additional space beyond the end of mapping. */
|
||||||
|
ptr = mmap(map->dxb + map->limit, limit - map->limit, mmap_prot,
|
||||||
|
mmap_flags
|
||||||
|
#if defined(MAP_FIXED_NOREPLACE)
|
||||||
|
| MAP_FIXED_NOREPLACE
|
||||||
|
#endif /* MAP_FIXED_NOREPLACE */
|
||||||
|
,
|
||||||
|
map->fd, map->limit);
|
||||||
|
if (ptr == map->dxb + map->limit)
|
||||||
|
ptr = map->dxb;
|
||||||
|
else if (ptr != MAP_FAILED) {
|
||||||
|
/* the desired address is busy, unmap unsuitable one */
|
||||||
|
if (unlikely(munmap(ptr, limit - map->limit)))
|
||||||
|
return errno;
|
||||||
|
ptr = MAP_FAILED;
|
||||||
|
} else {
|
||||||
|
const int err = errno;
|
||||||
|
switch (err) {
|
||||||
|
default:
|
||||||
|
return err;
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
case ENOMEM:
|
case ENOMEM:
|
||||||
case EFAULT /* MADV_DODUMP / MADV_DONTDUMP are mixed for mmap-range */:
|
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||||
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
|
case EEXIST: /* address busy */
|
||||||
|
case EINVAL: /* kernel don't support MAP_FIXED_NOREPLACE */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
#else
|
}
|
||||||
if (!may_move)
|
|
||||||
|
if (ptr == MAP_FAILED) {
|
||||||
|
/* unmap and map again whole region */
|
||||||
|
if (!may_move) {
|
||||||
/* TODO: Perhaps here it is worth to implement suspend/resume threads
|
/* TODO: Perhaps here it is worth to implement suspend/resume threads
|
||||||
* and perform unmap/map as like for Windows. */
|
* and perform unmap/map as like for Windows. */
|
||||||
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
if (unlikely(munmap(map->address, map->limit)))
|
if (unlikely(munmap(map->address, map->limit)))
|
||||||
return errno;
|
return errno;
|
||||||
|
|
||||||
unsigned mmap_flags =
|
ptr = mmap(map->address, limit, mmap_prot, mmap_flags, map->fd, 0);
|
||||||
MAP_CONCEAL | MAP_SHARED | MAP_FILE |
|
|
||||||
(F_ISSET(flags, MDBX_UTTERLY_NOSYNC) ? MAP_NOSYNC : 0);
|
|
||||||
#ifdef MAP_FIXED
|
|
||||||
if (!may_move)
|
|
||||||
mmap_flags |= MAP_FIXED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *ptr =
|
|
||||||
mmap(map->address, limit,
|
|
||||||
(flags & MDBX_WRITEMAP) ? PROT_READ | PROT_WRITE : PROT_READ,
|
|
||||||
mmap_flags, map->fd, 0);
|
|
||||||
if (unlikely(ptr == MAP_FAILED)) {
|
if (unlikely(ptr == MAP_FAILED)) {
|
||||||
ptr = mmap(map->address, map->limit,
|
ptr = mmap(map->address, map->limit, mmap_prot, mmap_flags, map->fd, 0);
|
||||||
(flags & MDBX_WRITEMAP) ? PROT_READ | PROT_WRITE : PROT_READ,
|
|
||||||
mmap_flags, map->fd, 0);
|
|
||||||
if (unlikely(ptr == MAP_FAILED)) {
|
if (unlikely(ptr == MAP_FAILED)) {
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(map->address, map->current);
|
VALGRIND_MAKE_MEM_NOACCESS(map->address, map->current);
|
||||||
/* Unpoisoning is required for ASAN to avoid false-positive diagnostic
|
/* Unpoisoning is required for ASAN to avoid false-positive diagnostic
|
||||||
@ -1640,34 +1682,36 @@ retry_mapview:;
|
|||||||
map->address = nullptr;
|
map->address = nullptr;
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||||
|
limit = map->limit;
|
||||||
}
|
}
|
||||||
#endif /* !MREMAP_MAYMOVE */
|
}
|
||||||
|
|
||||||
if (map->address != ptr) {
|
assert(ptr && ptr != MAP_FAILED);
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(map->address, map->current);
|
if (map->address != ptr) {
|
||||||
/* Unpoisoning is required for ASAN to avoid false-positive diagnostic
|
VALGRIND_MAKE_MEM_NOACCESS(map->address, map->current);
|
||||||
* when this memory will re-used by malloc or another mmaping.
|
/* Unpoisoning is required for ASAN to avoid false-positive diagnostic
|
||||||
* See https://github.com/erthink/libmdbx/pull/93#issuecomment-613687203
|
* when this memory will re-used by malloc or another mmaping.
|
||||||
*/
|
* See https://github.com/erthink/libmdbx/pull/93#issuecomment-613687203
|
||||||
ASAN_UNPOISON_MEMORY_REGION(map->address, map->limit);
|
*/
|
||||||
|
ASAN_UNPOISON_MEMORY_REGION(map->address, map->limit);
|
||||||
|
|
||||||
VALGRIND_MAKE_MEM_DEFINED(ptr, map->current);
|
VALGRIND_MAKE_MEM_DEFINED(ptr, map->current);
|
||||||
ASAN_UNPOISON_MEMORY_REGION(ptr, map->current);
|
ASAN_UNPOISON_MEMORY_REGION(ptr, map->current);
|
||||||
map->address = ptr;
|
map->address = ptr;
|
||||||
}
|
}
|
||||||
map->limit = limit;
|
map->limit = limit;
|
||||||
|
|
||||||
#ifdef MADV_DONTFORK
|
#ifdef MADV_DONTFORK
|
||||||
if (unlikely(madvise(map->address, map->limit, MADV_DONTFORK) != 0))
|
if (unlikely(madvise(map->address, map->limit, MADV_DONTFORK) != 0))
|
||||||
return errno;
|
return errno;
|
||||||
#endif /* MADV_DONTFORK */
|
#endif /* MADV_DONTFORK */
|
||||||
|
|
||||||
#ifdef MADV_NOHUGEPAGE
|
#ifdef MADV_NOHUGEPAGE
|
||||||
(void)madvise(map->address, map->limit, MADV_NOHUGEPAGE);
|
(void)madvise(map->address, map->limit, MADV_NOHUGEPAGE);
|
||||||
#endif /* MADV_NOHUGEPAGE */
|
#endif /* MADV_NOHUGEPAGE */
|
||||||
}
|
|
||||||
#endif
|
#endif /* POSIX / Windows */
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user