mirror of
https://github.com/isar/libmdbx.git
synced 2024-10-30 11:29:19 +08:00
mdbx: чуть больше контроля и паранойи для страховки от дефектов mremap()
.
Есть основание полагать, что mremap() может возвращать MAP_FAILED, но НЕ устанавливать errno в некоторых пограничных ситуациях. Например, когда системных ресурсов не хватает на актуализацию/копирование/клонирование состояния отображения на финальной стадии, в том числе из-за раскраски исходного отображения разными флагами через madvise().
This commit is contained in:
parent
51a765a5a7
commit
80f9f73a5e
39
src/osal.c
39
src/osal.c
@ -2166,6 +2166,7 @@ MDBX_INTERNAL_FUNC int osal_mmap(const int flags, osal_mmap_t *map,
|
||||
map->limit = 0;
|
||||
map->current = 0;
|
||||
map->address = nullptr;
|
||||
assert(errno != 0);
|
||||
return errno;
|
||||
}
|
||||
map->limit = limit;
|
||||
@ -2204,8 +2205,10 @@ MDBX_INTERNAL_FUNC int osal_munmap(osal_mmap_t *map) {
|
||||
if (!NT_SUCCESS(rc))
|
||||
ntstatus2errcode(rc);
|
||||
#else
|
||||
if (unlikely(munmap(map->address, map->limit)))
|
||||
if (unlikely(munmap(map->address, map->limit))) {
|
||||
assert(errno != 0);
|
||||
return errno;
|
||||
}
|
||||
#endif /* ! Windows */
|
||||
|
||||
map->limit = 0;
|
||||
@ -2428,8 +2431,10 @@ retry_mapview:;
|
||||
if (limit < map->limit) {
|
||||
/* unmap an excess at end of mapping. */
|
||||
// coverity[offset_free : FALSE]
|
||||
if (unlikely(munmap(map->dxb + limit, map->limit - limit)))
|
||||
if (unlikely(munmap(map->dxb + limit, map->limit - limit))) {
|
||||
assert(errno != 0);
|
||||
return errno;
|
||||
}
|
||||
map->limit = limit;
|
||||
return rc;
|
||||
}
|
||||
@ -2441,14 +2446,19 @@ retry_mapview:;
|
||||
assert(limit > map->limit);
|
||||
uint8_t *ptr = MAP_FAILED;
|
||||
|
||||
#if defined(MREMAP_MAYMOVE)
|
||||
#if (defined(__linux__) || defined(__gnu_linux__)) && defined(_GNU_SOURCE)
|
||||
ptr = mremap(map->address, map->limit, limit,
|
||||
(flags & MDBX_MRESIZE_MAY_MOVE) ? MREMAP_MAYMOVE : 0);
|
||||
#if defined(MREMAP_MAYMOVE)
|
||||
(flags & MDBX_MRESIZE_MAY_MOVE) ? MREMAP_MAYMOVE :
|
||||
#endif /* MREMAP_MAYMOVE */
|
||||
0);
|
||||
if (ptr == MAP_FAILED) {
|
||||
err = errno;
|
||||
assert(err != 0);
|
||||
switch (err) {
|
||||
default:
|
||||
return err;
|
||||
case 0 /* paranoia */:
|
||||
case EAGAIN:
|
||||
case ENOMEM:
|
||||
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||
@ -2456,7 +2466,7 @@ retry_mapview:;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* MREMAP_MAYMOVE */
|
||||
#endif /* Linux & _GNU_SOURCE */
|
||||
|
||||
const unsigned mmap_flags =
|
||||
MAP_CONCEAL | MAP_SHARED | MAP_FILE | MAP_NORESERVE |
|
||||
@ -2469,17 +2479,22 @@ retry_mapview:;
|
||||
ptr = mmap(map->dxb + map->limit, limit - map->limit, mmap_prot,
|
||||
mmap_flags | 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)))
|
||||
if (unlikely(munmap(ptr, limit - map->limit))) {
|
||||
assert(errno != 0);
|
||||
return errno;
|
||||
}
|
||||
ptr = MAP_FAILED;
|
||||
} else {
|
||||
err = errno;
|
||||
assert(err != 0);
|
||||
switch (err) {
|
||||
default:
|
||||
return err;
|
||||
case 0 /* paranoia */:
|
||||
case EAGAIN:
|
||||
case ENOMEM:
|
||||
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||
@ -2498,8 +2513,10 @@ retry_mapview:;
|
||||
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||
}
|
||||
|
||||
if (unlikely(munmap(map->address, map->limit)))
|
||||
if (unlikely(munmap(map->address, map->limit))) {
|
||||
assert(errno != 0);
|
||||
return errno;
|
||||
}
|
||||
|
||||
// coverity[pass_freed_arg : FALSE]
|
||||
ptr = mmap(map->address, limit, mmap_prot,
|
||||
@ -2543,6 +2560,7 @@ retry_mapview:;
|
||||
map->limit = 0;
|
||||
map->current = 0;
|
||||
map->address = nullptr;
|
||||
assert(errno != 0);
|
||||
return errno;
|
||||
}
|
||||
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||
@ -2569,8 +2587,10 @@ retry_mapview:;
|
||||
|
||||
#if MDBX_ENABLE_MADVISE
|
||||
#ifdef MADV_DONTFORK
|
||||
if (unlikely(madvise(map->address, map->limit, MADV_DONTFORK) != 0))
|
||||
if (unlikely(madvise(map->address, map->limit, MADV_DONTFORK) != 0)) {
|
||||
assert(errno != 0);
|
||||
return errno;
|
||||
}
|
||||
#endif /* MADV_DONTFORK */
|
||||
#ifdef MADV_NOHUGEPAGE
|
||||
(void)madvise(map->address, map->limit, MADV_NOHUGEPAGE);
|
||||
@ -2579,6 +2599,9 @@ retry_mapview:;
|
||||
|
||||
#endif /* POSIX / Windows */
|
||||
|
||||
assert(rc != MDBX_SUCCESS ||
|
||||
(map->address != nullptr && map->address != MAP_FAILED &&
|
||||
map->current == size && map->limit == limit));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user