mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-21 18:28:20 +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->limit = 0;
|
||||||
map->current = 0;
|
map->current = 0;
|
||||||
map->address = nullptr;
|
map->address = nullptr;
|
||||||
|
assert(errno != 0);
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
map->limit = limit;
|
map->limit = limit;
|
||||||
@ -2204,8 +2205,10 @@ MDBX_INTERNAL_FUNC int osal_munmap(osal_mmap_t *map) {
|
|||||||
if (!NT_SUCCESS(rc))
|
if (!NT_SUCCESS(rc))
|
||||||
ntstatus2errcode(rc);
|
ntstatus2errcode(rc);
|
||||||
#else
|
#else
|
||||||
if (unlikely(munmap(map->address, map->limit)))
|
if (unlikely(munmap(map->address, map->limit))) {
|
||||||
|
assert(errno != 0);
|
||||||
return errno;
|
return errno;
|
||||||
|
}
|
||||||
#endif /* ! Windows */
|
#endif /* ! Windows */
|
||||||
|
|
||||||
map->limit = 0;
|
map->limit = 0;
|
||||||
@ -2428,8 +2431,10 @@ retry_mapview:;
|
|||||||
if (limit < map->limit) {
|
if (limit < map->limit) {
|
||||||
/* unmap an excess at end of mapping. */
|
/* unmap an excess at end of mapping. */
|
||||||
// coverity[offset_free : FALSE]
|
// 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;
|
return errno;
|
||||||
|
}
|
||||||
map->limit = limit;
|
map->limit = limit;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -2441,14 +2446,19 @@ retry_mapview:;
|
|||||||
assert(limit > map->limit);
|
assert(limit > map->limit);
|
||||||
uint8_t *ptr = MAP_FAILED;
|
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,
|
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) {
|
if (ptr == MAP_FAILED) {
|
||||||
err = errno;
|
err = errno;
|
||||||
|
assert(err != 0);
|
||||||
switch (err) {
|
switch (err) {
|
||||||
default:
|
default:
|
||||||
return err;
|
return err;
|
||||||
|
case 0 /* paranoia */:
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
case ENOMEM:
|
case ENOMEM:
|
||||||
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||||
@ -2456,7 +2466,7 @@ retry_mapview:;
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* MREMAP_MAYMOVE */
|
#endif /* Linux & _GNU_SOURCE */
|
||||||
|
|
||||||
const unsigned mmap_flags =
|
const unsigned mmap_flags =
|
||||||
MAP_CONCEAL | MAP_SHARED | MAP_FILE | MAP_NORESERVE |
|
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,
|
ptr = mmap(map->dxb + map->limit, limit - map->limit, mmap_prot,
|
||||||
mmap_flags | MAP_FIXED_NOREPLACE, map->fd, map->limit);
|
mmap_flags | MAP_FIXED_NOREPLACE, map->fd, map->limit);
|
||||||
if (ptr == map->dxb + map->limit)
|
if (ptr == map->dxb + map->limit)
|
||||||
|
/* успешно прилепили отображение в конец */
|
||||||
ptr = map->dxb;
|
ptr = map->dxb;
|
||||||
else if (ptr != MAP_FAILED) {
|
else if (ptr != MAP_FAILED) {
|
||||||
/* the desired address is busy, unmap unsuitable one */
|
/* 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;
|
return errno;
|
||||||
|
}
|
||||||
ptr = MAP_FAILED;
|
ptr = MAP_FAILED;
|
||||||
} else {
|
} else {
|
||||||
err = errno;
|
err = errno;
|
||||||
|
assert(err != 0);
|
||||||
switch (err) {
|
switch (err) {
|
||||||
default:
|
default:
|
||||||
return err;
|
return err;
|
||||||
|
case 0 /* paranoia */:
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
case ENOMEM:
|
case ENOMEM:
|
||||||
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||||
@ -2498,8 +2513,10 @@ retry_mapview:;
|
|||||||
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
return MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(munmap(map->address, map->limit)))
|
if (unlikely(munmap(map->address, map->limit))) {
|
||||||
|
assert(errno != 0);
|
||||||
return errno;
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
// coverity[pass_freed_arg : FALSE]
|
// coverity[pass_freed_arg : FALSE]
|
||||||
ptr = mmap(map->address, limit, mmap_prot,
|
ptr = mmap(map->address, limit, mmap_prot,
|
||||||
@ -2543,6 +2560,7 @@ retry_mapview:;
|
|||||||
map->limit = 0;
|
map->limit = 0;
|
||||||
map->current = 0;
|
map->current = 0;
|
||||||
map->address = nullptr;
|
map->address = nullptr;
|
||||||
|
assert(errno != 0);
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
|
rc = MDBX_UNABLE_EXTEND_MAPSIZE;
|
||||||
@ -2569,8 +2587,10 @@ retry_mapview:;
|
|||||||
|
|
||||||
#if MDBX_ENABLE_MADVISE
|
#if MDBX_ENABLE_MADVISE
|
||||||
#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)) {
|
||||||
|
assert(errno != 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);
|
||||||
@ -2579,6 +2599,9 @@ retry_mapview:;
|
|||||||
|
|
||||||
#endif /* POSIX / Windows */
|
#endif /* POSIX / Windows */
|
||||||
|
|
||||||
|
assert(rc != MDBX_SUCCESS ||
|
||||||
|
(map->address != nullptr && map->address != MAP_FAILED &&
|
||||||
|
map->current == size && map->limit == limit));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user